2121import  java .util .HashSet ;
2222import  java .util .List ;
2323import  java .util .Map ;
24+ import  java .util .Objects ;
2425import  java .util .Optional ;
2526import  java .util .Set ;
2627import  java .util .Stack ;
@@ -70,24 +71,20 @@ public SortedSetDocValues ordinals(LeafReaderContext context) throws IOException
7071        throw  new  UnsupportedOperationException ();
7172    }
7273
73-     private  record  IgnoredSourceRowStrideReader <T >(String  fieldName , Reader <T > reader ) implements  RowStrideReader  {
74-         @ Override 
75-         public  void  read (int  docId , StoredFields  storedFields , Builder  builder ) throws  IOException  {
76-             var  ignoredSource  = storedFields .storedFields ().get (IgnoredSourceFieldMapper .NAME );
77-             if  (ignoredSource  == null ) {
78-                 builder .appendNull ();
79-                 return ;
80-             }
81- 
82-             Map <String , List <IgnoredSourceFieldMapper .NameValue >> valuesForFieldAndParents  = new  HashMap <>();
74+     private  static  final  class  IgnoredSourceRowStrideReader <T > implements  RowStrideReader  {
75+         private  final  String  fieldName ;
76+         private  final  Reader <T > reader ;
77+         private  final  Set <String > fieldNames ;
8378
79+         private  IgnoredSourceRowStrideReader (String  fieldName , Reader <T > reader ) {
80+             this .fieldName  = fieldName ;
81+             this .reader  = reader ;
8482            // Contains name of the field and all its parents 
85-             Set < String >  fieldNames  = new  HashSet <>() {
83+             this . fieldNames  = new  HashSet <>() {
8684                {
8785                    add ("_doc" );
8886                }
8987            };
90- 
9188            var  current  = new  StringBuilder ();
9289            for  (String  part  : fieldName .split ("\\ ." )) {
9390                if  (current .isEmpty () == false ) {
@@ -96,11 +93,21 @@ public void read(int docId, StoredFields storedFields, Builder builder) throws I
9693                current .append (part );
9794                fieldNames .add (current .toString ());
9895            }
96+         }
9997
98+         @ Override 
99+         public  void  read (int  docId , StoredFields  storedFields , Builder  builder ) throws  IOException  {
100+             var  ignoredSource  = storedFields .storedFields ().get (IgnoredSourceFieldMapper .NAME );
101+             if  (ignoredSource  == null ) {
102+                 builder .appendNull ();
103+                 return ;
104+             }
105+ 
106+             Map <String , IgnoredSourceFieldMapper .NameValue > valuesForFieldAndParents  = new  HashMap <>();
100107            for  (Object  value  : ignoredSource ) {
101108                IgnoredSourceFieldMapper .NameValue  nameValue  = IgnoredSourceFieldMapper .decode (value );
102109                if  (fieldNames .contains (nameValue .name ())) {
103-                     valuesForFieldAndParents .computeIfAbsent (nameValue .name (), k  ->  new   ArrayList <>()). add ( nameValue );
110+                     valuesForFieldAndParents .putIfAbsent (nameValue .name (), nameValue );
104111                }
105112            }
106113
@@ -130,41 +137,35 @@ public void read(int docId, StoredFields storedFields, Builder builder) throws I
130137            }
131138        }
132139
133-         private  void  readFromFieldValue (List <IgnoredSourceFieldMapper .NameValue > nameValues , List <T > blockValues ) throws  IOException  {
134-             if  (nameValues .isEmpty ()) {
140+         private  void  readFromFieldValue (IgnoredSourceFieldMapper .NameValue  nameValue , List <T > blockValues ) throws  IOException  {
141+             // Leaf field is stored directly (not as a part of a parent object), let's try to decode it. 
142+             Optional <Object > singleValue  = XContentDataHelper .decode (nameValue .value ());
143+             if  (singleValue .isPresent ()) {
144+                 reader .convertValue (singleValue .get (), blockValues );
135145                return ;
136146            }
137147
138-             for  (var  nameValue  : nameValues ) {
139-                 // Leaf field is stored directly (not as a part of a parent object), let's try to decode it. 
140-                 Optional <Object > singleValue  = XContentDataHelper .decode (nameValue .value ());
141-                 if  (singleValue .isPresent ()) {
142-                     reader .convertValue (singleValue .get (), blockValues );
143-                     continue ;
144-                 }
148+             // We have a value for this field but it's an array or an object 
149+             var  type  = XContentDataHelper .decodeType (nameValue .value ());
150+             assert  type .isPresent ();
145151
146-                 // We have a value for this field but it's an array or an object 
147-                 var  type  = XContentDataHelper .decodeType (nameValue .value ());
148-                 assert  type .isPresent ();
149- 
150-                 try  (
151-                     XContentParser  parser  = type .get ()
152-                         .xContent ()
153-                         .createParser (
154-                             XContentParserConfiguration .EMPTY ,
155-                             nameValue .value ().bytes ,
156-                             nameValue .value ().offset  + 1 ,
157-                             nameValue .value ().length  - 1 
158-                         )
159-                 ) {
160-                     parser .nextToken ();
161-                     parseWithReader (parser , blockValues );
162-                 }
152+             try  (
153+                 XContentParser  parser  = type .get ()
154+                     .xContent ()
155+                     .createParser (
156+                         XContentParserConfiguration .EMPTY ,
157+                         nameValue .value ().bytes ,
158+                         nameValue .value ().offset  + 1 ,
159+                         nameValue .value ().length  - 1 
160+                     )
161+             ) {
162+                 parser .nextToken ();
163+                 parseWithReader (parser , blockValues );
163164            }
164165        }
165166
166167        private  void  readFromParentValue (
167-             Map <String , List < IgnoredSourceFieldMapper .NameValue > > valuesForFieldAndParents ,
168+             Map <String , IgnoredSourceFieldMapper .NameValue > valuesForFieldAndParents ,
168169            List <T > blockValues 
169170        ) throws  IOException  {
170171            if  (valuesForFieldAndParents .isEmpty ()) {
@@ -174,11 +175,8 @@ private void readFromParentValue(
174175            // If a parent object is stored at a particular level its children won't be stored. 
175176            // So we should only ever have one parent here. 
176177            assert  valuesForFieldAndParents .size () == 1  : "_ignored_source field contains multiple levels of the same object" ;
177-             var  parentValues  = valuesForFieldAndParents .values ().iterator ().next ();
178- 
179-             for  (var  nameValue  : parentValues ) {
180-                 parseFieldFromParent (nameValue , blockValues );
181-             }
178+             var  parentValue  = valuesForFieldAndParents .values ().iterator ().next ();
179+             parseFieldFromParent (parentValue , blockValues );
182180        }
183181
184182        private  void  parseFieldFromParent (IgnoredSourceFieldMapper .NameValue  nameValue , List <T > blockValues ) throws  IOException  {
@@ -243,6 +241,33 @@ private void parseWithReader(XContentParser parser, List<T> blockValues) throws
243241        public  boolean  canReuse (int  startingDocID ) {
244242            return  true ;
245243        }
244+ 
245+         public  String  fieldName () {
246+             return  fieldName ;
247+         }
248+ 
249+         public  Reader <T > reader () {
250+             return  reader ;
251+         }
252+ 
253+         @ Override 
254+         public  boolean  equals (Object  obj ) {
255+             if  (obj  == this ) return  true ;
256+             if  (obj  == null  || obj .getClass () != this .getClass ()) return  false ;
257+             var  that  = (IgnoredSourceRowStrideReader ) obj ;
258+             return  Objects .equals (this .fieldName , that .fieldName ) && Objects .equals (this .reader , that .reader );
259+         }
260+ 
261+         @ Override 
262+         public  int  hashCode () {
263+             return  Objects .hash (fieldName , reader );
264+         }
265+ 
266+         @ Override 
267+         public  String  toString () {
268+             return  "IgnoredSourceRowStrideReader["  + "fieldName="  + fieldName  + ", "  + "reader="  + reader  + ']' ;
269+         }
270+ 
246271    }
247272
248273    /** 
0 commit comments