33import java .util .Set ;
44
55import tools .jackson .core .*;
6+ import tools .jackson .core .exc .StreamReadException ;
67import tools .jackson .core .io .CharTypes ;
78import tools .jackson .core .io .ContentReference ;
9+ import tools .jackson .core .json .DupDetector ;
810
911/**
1012 * Extension of {@link TokenStreamContext}, which implements
@@ -23,6 +25,12 @@ public final class XmlReadContext
2325
2426 protected final XmlReadContext _parent ;
2527
28+ /**
29+ * Object used for checking for duplicate field names, if enabled
30+ * (null if not enabled)
31+ */
32+ protected final DupDetector _dups ;
33+
2634 // // // Location information (minus source reference)
2735
2836 protected int _lineNr ;
@@ -54,18 +62,27 @@ public final class XmlReadContext
5462 /**********************************************************************
5563 */
5664
57- public XmlReadContext (int type , XmlReadContext parent , int nestingDepth ,
65+ public XmlReadContext (int type , XmlReadContext parent , DupDetector dups ,
66+ int nestingDepth ,
5867 int lineNr , int colNr )
5968 {
6069 super ();
6170 _type = type ;
6271 _parent = parent ;
72+ _dups = dups ;
6373 _nestingDepth = nestingDepth ;
6474 _lineNr = lineNr ;
6575 _columnNr = colNr ;
6676 _index = -1 ;
6777 }
6878
79+ @ Deprecated // @since 3.0.2
80+ public XmlReadContext (int type , XmlReadContext parent , int nestingDepth ,
81+ int lineNr , int colNr )
82+ {
83+ this (type , parent , null , nestingDepth , lineNr , colNr );
84+ }
85+
6986 protected final void reset (int type , int lineNr , int colNr )
7087 {
7188 _type = type ;
@@ -76,6 +93,9 @@ protected final void reset(int type, int lineNr, int colNr)
7693 _currentValue = null ;
7794 _namesToWrap = null ;
7895 // _nestingDepth is fine since reused instance at same nesting level
96+ if (_dups != null ) {
97+ _dups .reset ();
98+ }
7999 }
80100
81101 @ Override
@@ -94,17 +114,23 @@ public void assignCurrentValue(Object v) {
94114 /**********************************************************************
95115 */
96116
117+ public static XmlReadContext createRootContext (DupDetector dups , int lineNr , int colNr ) {
118+ return new XmlReadContext (TYPE_ROOT , null , dups , 0 , lineNr , colNr );
119+ }
120+
121+ @ Deprecated // @since 3.0.2
97122 public static XmlReadContext createRootContext (int lineNr , int colNr ) {
98- return new XmlReadContext ( TYPE_ROOT , null , 0 , lineNr , colNr );
123+ return createRootContext ( null , lineNr , colNr );
99124 }
100125
101126 public final XmlReadContext createChildArrayContext (int lineNr , int colNr )
102127 {
103128 ++_index ; // not needed for Object, but does not hurt so no need to check curr type
104129 XmlReadContext ctxt = _child ;
105130 if (ctxt == null ) {
106- _child = ctxt = new XmlReadContext (TYPE_ARRAY , this , _nestingDepth +1 ,
107- lineNr , colNr );
131+ _child = ctxt = new XmlReadContext (TYPE_ARRAY , this ,
132+ (_dups == null ) ? null : _dups .child (),
133+ _nestingDepth +1 , lineNr , colNr );
108134 return ctxt ;
109135 }
110136 ctxt .reset (TYPE_ARRAY , lineNr , colNr );
@@ -116,8 +142,9 @@ public final XmlReadContext createChildObjectContext(int lineNr, int colNr)
116142 ++_index ; // not needed for Object, but does not hurt so no need to check curr type
117143 XmlReadContext ctxt = _child ;
118144 if (ctxt == null ) {
119- _child = ctxt = new XmlReadContext (TYPE_OBJECT , this , _nestingDepth +1 ,
120- lineNr , colNr );
145+ _child = ctxt = new XmlReadContext (TYPE_OBJECT , this ,
146+ (_dups == null ) ? null : _dups .child (),
147+ _nestingDepth +1 , lineNr , colNr );
121148 return ctxt ;
122149 }
123150 ctxt .reset (TYPE_OBJECT , lineNr , colNr );
@@ -159,15 +186,25 @@ public final TokenStreamLocation startLocation(ContentReference srcRef) {
159186 /**
160187 * Method called to mark start of new value, mostly to update `index`
161188 * for Array and Root contexts.
162- *
163- * @since 2.12
164189 */
165190 public final void valueStarted () {
166191 ++_index ;
167192 }
168193
169- public void setCurrentName (String name ) {
194+ public void setCurrentName (String name ) throws StreamReadException {
170195 _currentName = name ;
196+ if (_dups != null ) {
197+ _checkDup (_dups , name );
198+ }
199+ }
200+
201+ private static void _checkDup (DupDetector dd , String name ) throws StreamReadException
202+ {
203+ if (dd .isDup (name )) {
204+ Object src = dd .getSource ();
205+ throw new StreamReadException (((src instanceof JsonParser ) ? ((JsonParser ) src ) : null ),
206+ "Duplicate Object property \" " +name +"\" " );
207+ }
171208 }
172209
173210 public void setNamesToWrap (Set <String > namesToWrap ) {
@@ -181,7 +218,7 @@ public boolean shouldWrap(String localName) {
181218 protected void convertToArray () {
182219 _type = TYPE_ARRAY ;
183220 }
184-
221+
185222 /*
186223 /**********************************************************************
187224 /* Overridden standard methods
0 commit comments