2424import java .util .ArrayDeque ;
2525import java .util .Deque ;
2626import java .util .Iterator ;
27+ import java .util .List ;
2728import java .util .Map ;
2829
2930/**
@@ -64,23 +65,35 @@ public class ESONXContentParser extends AbstractXContentParser {
6465 private boolean closed = false ;
6566
6667 private static class ParseContext {
67- final Type type ;
68- final Iterator <?> iterator ;
69- final Object rawObject ; // Keep reference to raw ESON object for optimization
68+ private final Type type ;
69+ private final Iterator <?> iterator ;
70+ private final boolean isMutation ;
7071 boolean expectingValue = false ;
7172
7273 // For objects - use non-materializing iterator
7374 ParseContext (ESONSource .ESONObject obj ) {
7475 this .type = Type .OBJECT ;
7576 this .iterator = obj .entrySet (false ).iterator ();
76- this .rawObject = obj ;
77+ this .isMutation = false ;
7778 }
7879
7980 // For arrays - use non-materializing iterator
8081 ParseContext (ESONSource .ESONArray arr ) {
8182 this .type = Type .ARRAY ;
8283 this .iterator = arr .iterator (false );
83- this .rawObject = arr ;
84+ this .isMutation = false ;
85+ }
86+
87+ ParseContext (Map <String , Object > map ) {
88+ this .type = Type .OBJECT ;
89+ this .iterator = map .entrySet ().iterator ();
90+ this .isMutation = true ;
91+ }
92+
93+ ParseContext (List <Object > list ) {
94+ this .type = Type .ARRAY ;
95+ this .iterator = list .iterator ();
96+ this .isMutation = true ;
8497 }
8598
8699 enum Type {
@@ -100,6 +113,7 @@ public ESONXContentParser(
100113 this .values = root .objectValues ().get ();
101114 // Start with the root object context
102115 this .currentContext = new ParseContext (root );
116+ contextStack .addFirst (currentContext );
103117 this .xContentType = xContentType ;
104118 this .currentToken = null ; // Will be set to START_OBJECT on first nextToken()
105119 }
@@ -123,7 +137,6 @@ public Token nextToken() throws IOException {
123137 if (currentToken == null ) {
124138 // First call - return START_OBJECT for root
125139 currentToken = Token .START_OBJECT ;
126- contextStack .addFirst (currentContext );
127140 return currentToken ;
128141 }
129142
@@ -150,17 +163,21 @@ private Token advanceObjectToken() {
150163 } else {
151164 // Try to get next field - now working with raw types
152165 @ SuppressWarnings ("unchecked" )
153- Iterator <Map .Entry <String , ESONSource . Type >> objIter = (Iterator <Map .Entry <String , ESONSource . Type >>) currentContext .iterator ;
166+ Iterator <Map .Entry <String , Object >> objIter = (Iterator <Map .Entry <String , Object >>) currentContext .iterator ;
154167
155168 if (objIter .hasNext ()) {
156- Map .Entry <String , ESONSource .Type > entry = objIter .next ();
157- currentFieldName = entry .getKey ();
158- currentEsonType = entry .getValue ();
159-
160169 // Reset value computation state
161170 currentValue = null ;
162171 valueComputed = false ;
163172
173+ Map .Entry <String , Object > entry = objIter .next ();
174+ currentFieldName = entry .getKey ();
175+ if (currentContext .isMutation ) {
176+ currentEsonType = new ESONSource .Mutation (entry .getValue ());
177+ } else {
178+ currentEsonType = (ESONSource .Type ) entry .getValue ();
179+ }
180+
164181 currentContext .expectingValue = true ;
165182 currentToken = Token .FIELD_NAME ;
166183 return currentToken ;
@@ -173,15 +190,20 @@ private Token advanceObjectToken() {
173190
174191 private Token advanceArrayToken () {
175192 @ SuppressWarnings ("unchecked" )
176- Iterator <ESONSource . Type > arrIter = (Iterator <ESONSource . Type >) currentContext .iterator ;
193+ Iterator <Object > arrIter = (Iterator <Object >) currentContext .iterator ;
177194
178195 if (arrIter .hasNext ()) {
179- currentEsonType = arrIter .next ();
180-
181196 // Reset value computation state
182197 currentValue = null ;
183198 valueComputed = false ;
184199
200+ Object next = arrIter .next ();
201+ if (currentContext .isMutation ) {
202+ currentEsonType = new ESONSource .Mutation (next );
203+ } else {
204+ currentEsonType = (ESONSource .Type ) next ;
205+ }
206+
185207 return emitValue (currentEsonType );
186208 } else {
187209 // End of array
@@ -196,18 +218,19 @@ private Token endCurrentContext(Token endToken) {
196218 return currentToken ;
197219 }
198220
221+ @ SuppressWarnings ("unchecked" )
199222 private Token emitValue (ESONSource .Type esonType ) {
200223 if (esonType == null ) {
201224 currentToken = Token .VALUE_NULL ;
202225 } else if (esonType instanceof ESONSource .ESONObject obj ) {
203226 // Push new object context
204- contextStack .addFirst (currentContext );
205227 currentContext = new ParseContext (obj );
228+ contextStack .addFirst (currentContext );
206229 currentToken = Token .START_OBJECT ;
207230 } else if (esonType instanceof ESONSource .ESONArray arr ) {
208231 // Push new array context
209- contextStack .addFirst (currentContext );
210232 currentContext = new ParseContext (arr );
233+ contextStack .addFirst (currentContext );
211234 currentToken = Token .START_ARRAY ;
212235 } else if (esonType instanceof ESONSource .FixedValue fixedVal ) {
213236 currentToken = Token .VALUE_NUMBER ;
@@ -233,13 +256,13 @@ private Token emitValue(ESONSource.Type esonType) {
233256 currentToken = Token .VALUE_BOOLEAN ;
234257 } else if (mutatedValue instanceof byte []) {
235258 currentToken = Token .VALUE_EMBEDDED_OBJECT ;
236- } else if (mutatedValue instanceof ESONSource .ESONObject obj ) {
259+ } else if (mutatedValue instanceof Map ) {
260+ currentContext = new ParseContext ((Map <String , Object >) mutatedValue );
237261 contextStack .addFirst (currentContext );
238- currentContext = new ParseContext (obj );
239262 currentToken = Token .START_OBJECT ;
240- } else if (mutatedValue instanceof ESONSource .ESONArray arr ) {
263+ } else if (mutatedValue instanceof List ) {
264+ currentContext = new ParseContext ((List <Object >) mutatedValue );
241265 contextStack .addFirst (currentContext );
242- currentContext = new ParseContext (arr );
243266 currentToken = Token .START_ARRAY ;
244267 } else {
245268 throw new IllegalStateException ("Unknown mutation value type: " + mutatedValue .getClass ());
0 commit comments