1414import org .apache .lucene .util .automaton .CharacterRunAutomaton ;
1515import org .apache .lucene .util .automaton .Operations ;
1616import org .elasticsearch .common .regex .Regex ;
17- import org .elasticsearch .ingest .ESONIndexed ;
1817import org .elasticsearch .xcontent .XContentParser ;
1918
2019import java .io .IOException ;
@@ -29,23 +28,31 @@ public class XContentParserFilter {
2928
3029 private static final int MAX_DETERMINIZED_STATES = 50_000 ;
3130
32- public static Map <String , Object > filter (Map < String , Object > map , String [] includes , String [] excludes ) {
33- return filter (includes , excludes ).apply (map );
31+ public static Map <String , Object > filter (XContentParser parser , String [] includes ) {
32+ return filter (includes ).apply (parser );
3433 }
3534
3635 /**
3736 * Returns a function that filters a document map based on the given include and exclude rules.
38- * @see #filter(Map, String[] , String[]) for details
37+ * @see #filter(XContentParser , String[]) for details
3938 */
40- public static Function <Map < String , Object >, Map <String , Object >> filter (String [] includes , String [] excludes ) {
39+ public static Function <XContentParser , Map <String , Object >> filter (String [] includes ) {
4140 CharacterRunAutomaton matchAllAutomaton = new CharacterRunAutomaton (Automata .makeAnyString ());
4241 CharacterRunAutomaton include = compileAutomaton (includes , matchAllAutomaton );
43- CharacterRunAutomaton exclude = compileAutomaton (excludes , new CharacterRunAutomaton (Automata .makeEmpty ()));
4442
4543 // NOTE: We cannot use Operations.minus because of the special case that
4644 // we want all sub properties to match as soon as an object matches
4745
48- return (map ) -> filter ((XContentParser ) null , include , 0 , exclude , 0 , matchAllAutomaton );
46+ return (parser ) -> {
47+ XContentParser .Token startObjectToken ;
48+ try {
49+ startObjectToken = parser .nextToken ();
50+ assert startObjectToken == XContentParser .Token .START_OBJECT ;
51+ return filter (parser , include , 0 , matchAllAutomaton );
52+ } catch (IOException e ) {
53+ throw new UncheckedIOException (e );
54+ }
55+ };
4956 }
5057
5158 public static CharacterRunAutomaton compileAutomaton (String [] patterns , CharacterRunAutomaton defaultValue ) {
@@ -83,168 +90,86 @@ private static Map<String, Object> filter(
8390 XContentParser parser ,
8491 CharacterRunAutomaton includeAutomaton ,
8592 int initialIncludeState ,
86- CharacterRunAutomaton excludeAutomaton ,
87- int initialExcludeState ,
8893 CharacterRunAutomaton matchAllAutomaton
89- ) {
94+ ) throws IOException {
9095 Map <String , Object > filtered = new HashMap <>();
91- try {
92- XContentParser .Token startObjectToken = parser .nextToken ();
93- assert startObjectToken == XContentParser .Token .START_OBJECT ;
94- XContentParser .Token token = parser .nextToken ();
95- while (true ) {
96- if (token == XContentParser .Token .END_OBJECT ) {
97- return filtered ;
98- }
99-
100- token = parser .nextToken ();
101- assert token == XContentParser .Token .FIELD_NAME ;
102- String key = parser .currentName ();
103- token = parser .nextToken ();
104- int includeState = step (includeAutomaton , key , initialIncludeState );
105- if (includeState == -1 ) {
106- parser .skipChildren ();
107- continue ;
108- }
109-
110- break ;
111- }
112- } catch (IOException e ) {
113- throw new UncheckedIOException (e );
114- }
115- ESONIndexed .ESONObject map = null ;
116- for (Map .Entry <String , ?> entry : map .entrySet ()) {
117- String key = entry .getKey ();
96+ XContentParser .Token token ;
97+ while ((token = parser .nextToken ()) != XContentParser .Token .END_OBJECT ) {
11898
99+ assert token == XContentParser .Token .FIELD_NAME ;
100+ String key = parser .currentName ();
101+ // Now value token
102+ token = parser .nextToken ();
119103 int includeState = step (includeAutomaton , key , initialIncludeState );
120104 if (includeState == -1 ) {
105+ parser .skipChildren ();
121106 continue ;
122107 }
123108
124- int excludeState = step (excludeAutomaton , key , initialExcludeState );
125- if (excludeState != -1 && excludeAutomaton .isAccept (excludeState )) {
126- continue ;
127- }
128-
129- Object value ;
130- if (entry instanceof ESONIndexed .ESONObject .LazyEntry lazyEntry && lazyEntry .isUTF8Bytes ()) {
131- value = lazyEntry .utf8Bytes ();
132- } else {
133- value = entry .getValue ();
134- }
135-
136109 CharacterRunAutomaton subIncludeAutomaton = includeAutomaton ;
137110 int subIncludeState = includeState ;
138- if (includeAutomaton .isAccept (includeState )) {
139- if (excludeState == -1 || excludeAutomaton .step (excludeState , '.' ) == -1 ) {
140- // the exclude has no chances to match inner properties
141- filtered .put (key , value );
142- continue ;
143- } else {
144- // the object matched, so consider that the include matches every inner property
145- // we only care about excludes now
146- subIncludeAutomaton = matchAllAutomaton ;
147- subIncludeState = 0 ;
148- }
149- }
150-
151- if (value instanceof Map ) {
152-
111+ // if (includeAutomaton.isAccept(includeState)) {
112+ // while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
113+ // assert token == XContentParser.Token.FIELD_NAME;
114+ // String currentName = parser.currentName();
115+ // parser.nextToken();
116+ // filtered.put(currentName, parser.objectBytes());
117+ // }
118+ // continue;
119+ // }
120+
121+ if (token == XContentParser .Token .START_OBJECT ) {
153122 subIncludeState = subIncludeAutomaton .step (subIncludeState , '.' );
154123 if (subIncludeState == -1 ) {
124+ parser .skipChildren ();
155125 continue ;
156126 }
157- if (excludeState != -1 ) {
158- excludeState = excludeAutomaton .step (excludeState , '.' );
159- }
160-
161- @ SuppressWarnings ("unchecked" )
162- Map <String , Object > valueAsMap = (Map <String , Object >) value ;
163- Map <String , Object > filteredValue = filter (
164- (XContentParser ) null ,
165- // valueAsMap,
166- subIncludeAutomaton ,
167- subIncludeState ,
168- excludeAutomaton ,
169- excludeState ,
170- matchAllAutomaton
171- );
127+ Map <String , Object > filteredValue = filter (parser , subIncludeAutomaton , subIncludeState , matchAllAutomaton );
172128 if (includeAutomaton .isAccept (includeState ) || filteredValue .isEmpty () == false ) {
173129 filtered .put (key , filteredValue );
174130 }
175131
176- } else if (value instanceof Iterable ) {
177-
178- List <Object > filteredValue = filter (
179- (Iterable <?>) value ,
180- subIncludeAutomaton ,
181- subIncludeState ,
182- excludeAutomaton ,
183- excludeState ,
184- matchAllAutomaton
185- );
132+ } else if (token == XContentParser .Token .START_ARRAY ) {
133+ List <Object > filteredValue = filterArray (parser , subIncludeAutomaton , subIncludeState , matchAllAutomaton );
186134 if (includeAutomaton .isAccept (includeState ) || filteredValue .isEmpty () == false ) {
187135 filtered .put (key , filteredValue );
188136 }
189137
190138 } else {
191-
192139 // leaf property
193- if (includeAutomaton .isAccept (includeState ) && ( excludeState == - 1 || excludeAutomaton . isAccept ( excludeState ) == false ) ) {
194- filtered .put (key , value );
140+ if (includeAutomaton .isAccept (includeState )) {
141+ filtered .put (key , parser . objectText () );
195142 }
196-
197143 }
198-
199144 }
200145 return filtered ;
201146 }
202147
203- private static List <Object > filter (
204- Iterable <?> iterable ,
148+ private static List <Object > filterArray (
149+ XContentParser parser ,
205150 CharacterRunAutomaton includeAutomaton ,
206151 int initialIncludeState ,
207- CharacterRunAutomaton excludeAutomaton ,
208- int initialExcludeState ,
209152 CharacterRunAutomaton matchAllAutomaton
210- ) {
153+ ) throws IOException {
211154 List <Object > filtered = new ArrayList <>();
212155 boolean isInclude = includeAutomaton .isAccept (initialIncludeState );
213- for (Object value : iterable ) {
214- if (value instanceof Map ) {
156+ XContentParser .Token token ;
157+ while ((token = parser .nextToken ()) != XContentParser .Token .END_ARRAY ) {
158+ if (token == XContentParser .Token .START_OBJECT ) {
215159 int includeState = includeAutomaton .step (initialIncludeState , '.' );
216- int excludeState = initialExcludeState ;
217- if (excludeState != -1 ) {
218- excludeState = excludeAutomaton .step (excludeState , '.' );
219- }
220160 @ SuppressWarnings ("unchecked" )
221- Map <String , Object > filteredValue = filter (
222- (XContentParser ) null ,
223- // (Map<String, ?>) value,
224- includeAutomaton ,
225- includeState ,
226- excludeAutomaton ,
227- excludeState ,
228- matchAllAutomaton
229- );
161+ Map <String , Object > filteredValue = filter (parser , includeAutomaton , includeState , matchAllAutomaton );
230162 if (filteredValue .isEmpty () == false ) {
231163 filtered .add (filteredValue );
232164 }
233- } else if (value instanceof Iterable ) {
234- List <Object > filteredValue = filter (
235- (Iterable <?>) value ,
236- includeAutomaton ,
237- initialIncludeState ,
238- excludeAutomaton ,
239- initialExcludeState ,
240- matchAllAutomaton
241- );
165+ } else if (token == XContentParser .Token .START_ARRAY ) {
166+ List <Object > filteredValue = filterArray (parser , includeAutomaton , initialIncludeState , matchAllAutomaton );
242167 if (filteredValue .isEmpty () == false ) {
243168 filtered .add (filteredValue );
244169 }
245170 } else if (isInclude ) {
246171 // #22557: only accept this array value if the key we are on is accepted:
247- filtered .add (value );
172+ filtered .add (parser . objectBytes () );
248173 }
249174 }
250175 return filtered ;
0 commit comments