This is an automated email from the ASF dual-hosted git repository. fortino pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push: new 2f32f64a1c OAK-11475: fix param conversion for WordDelimiterFilter (#2070) 2f32f64a1c is described below commit 2f32f64a1c0d266c2918e64a2d631d2dddfc9da6 Author: Fabrizio Fortino <fabrizio.fort...@gmail.com> AuthorDate: Thu Feb 13 18:03:42 2025 +0100 OAK-11475: fix param conversion for WordDelimiterFilter (#2070) * tests: filters should always be ordered * OAK-11475: fix param conversion for WordDelimiterFilter --- .../index/ElasticCustomAnalyzerMappings.java | 10 +- .../plugins/index/FullTextAnalyzerCommonTest.java | 124 +++++++++++++++++---- 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticCustomAnalyzerMappings.java b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticCustomAnalyzerMappings.java index 35984d269b..97204a5556 100644 --- a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticCustomAnalyzerMappings.java +++ b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticCustomAnalyzerMappings.java @@ -28,6 +28,7 @@ import org.apache.lucene.analysis.miscellaneous.KeepWordFilterFactory; import org.apache.lucene.analysis.miscellaneous.KeywordMarkerFilterFactory; import org.apache.lucene.analysis.miscellaneous.LengthFilterFactory; import org.apache.lucene.analysis.miscellaneous.WordDelimiterFilterFactory; +import org.apache.lucene.analysis.miscellaneous.WordDelimiterGraphFilterFactory; import org.apache.lucene.analysis.ngram.EdgeNGramFilterFactory; import org.apache.lucene.analysis.ngram.NGramFilterFactory; import org.apache.lucene.analysis.pattern.PatternCaptureGroupFilterFactory; @@ -112,7 +113,7 @@ public class ElasticCustomAnalyzerMappings { LUCENE_ELASTIC_TRANSFORMERS = new LinkedHashMap<>(); - LUCENE_ELASTIC_TRANSFORMERS.put(WordDelimiterFilterFactory.class, luceneParams -> { + ParameterTransformer wordDelimiterParamTransformer = luceneParams -> { Consumer<String> transformFlag = flag -> luceneParams.computeIfPresent(flag, (k, v) -> Integer.parseInt(v.toString()) == 1); transformFlag.accept("generateWordParts"); @@ -126,9 +127,12 @@ public class ElasticCustomAnalyzerMappings { transformFlag.accept("stemEnglishPossessive"); return reKey.apply(luceneParams, Map.of( - "protectedTokens", "protected_words" + "protectedTokens", "protected_words", + "types", "type_table" )); - }); + }; + LUCENE_ELASTIC_TRANSFORMERS.put(WordDelimiterFilterFactory.class, wordDelimiterParamTransformer); + LUCENE_ELASTIC_TRANSFORMERS.put(WordDelimiterGraphFilterFactory.class, wordDelimiterParamTransformer); LUCENE_ELASTIC_TRANSFORMERS.put(TypeTokenFilterFactory.class, luceneParams -> { Object useWhitelist = luceneParams.remove("useWhitelist"); diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FullTextAnalyzerCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FullTextAnalyzerCommonTest.java index 47ecd0069e..b052f6268c 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FullTextAnalyzerCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FullTextAnalyzerCommonTest.java @@ -258,7 +258,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "whitespace"); - Tree stopFilter = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Stop"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree stopFilter = addFilter(filters, "Stop"); stopFilter.setProperty("words", "stop1.txt, stop2.txt"); stopFilter.addChild("stop1.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "foo"); @@ -281,6 +283,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree charFilters = anl.addChild(FulltextIndexConstants.ANL_CHAR_FILTERS); + charFilters.setOrderableChildren(true); addFilter(charFilters, "HTMLStrip"); Tree mappingFilter = addFilter(charFilters, "Mapping"); mappingFilter.setProperty("mapping", "mappings.txt"); @@ -288,6 +291,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { .setProperty(JCR_DATA, getHinduArabicMapping()); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); addFilter(filters, "LowerCase"); Tree stopFilter = addFilter(filters, "Stop"); stopFilter.setProperty("words", "stop1.txt, stop2.txt"); @@ -324,12 +328,14 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree charFilters = anl.addChild(FulltextIndexConstants.ANL_CHAR_FILTERS); + charFilters.setOrderableChildren(true); Tree mappingFilter = addFilter(charFilters, "Mapping"); mappingFilter.setProperty("mapping", "mapping-ISOLatin1Accent.txt"); mappingFilter.addChild("mapping-ISOLatin1Accent.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, mappings); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); Tree synFilter = addFilter(filters, "Synonym"); synFilter.setProperty("synonyms", "syn.txt"); synFilter.setProperty("format", "solr"); @@ -370,6 +376,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); addFilter(filters, "LowerCase"); addFilter(filters, "SpanishLightStem"); }); @@ -388,7 +395,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "KStem"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + addFilter(filters, "KStem"); }); Tree content = root.getTree("/").addChild("content"); @@ -406,6 +415,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); addFilter(filters, "LowerCase"); Tree marker = addFilter(filters, "KeywordMarker"); marker.setProperty("protected", "protected.txt"); @@ -428,6 +438,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree charFilters = anl.addChild(FulltextIndexConstants.ANL_CHAR_FILTERS); + charFilters.setOrderableChildren(true); Tree patternReplace = addFilter(charFilters, "PatternReplace"); patternReplace.setProperty("pattern", "(\\d+)-(?=\\d)"); patternReplace.setProperty("replacement", "$1"); @@ -449,7 +460,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Classic"); - addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Classic"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + addFilter(filters, "Classic"); }); Tree content = root.getTree("/").addChild("content"); @@ -465,7 +478,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree asciiFilter = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "AsciiFolding"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree asciiFilter = addFilter(filters, "AsciiFolding"); asciiFilter.setProperty("preserveOriginal", "true"); asciiFilter.setProperty(JCR_PRIMARYTYPE, NT_OAK_UNSTRUCTURED, Type.NAME); }); @@ -484,6 +499,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); Tree cjk = addFilter(filters, "CJKBigram"); cjk.setProperty("hangul", "false"); cjk.setProperty("hiragana", "false"); @@ -509,7 +525,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree commonGrams = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "CommonGrams"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree commonGrams = addFilter(filters, "CommonGrams"); commonGrams.setProperty("words", "words.txt"); commonGrams.addChild("words.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "is\nthe"); @@ -529,7 +547,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree delimited = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "DelimitedPayload"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree delimited = addFilter(filters, "DelimitedPayload"); delimited.setProperty("encoder", "float"); }); @@ -540,6 +560,39 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { assertEventually(() -> assertQuery("select * from [nt:base] where CONTAINS(*, 'brown')", List.of("/content/bar"))); } + @Test + public void fulltextSearchWithWordDelimiterFilter() throws Exception { + setup(List.of("foo"), idx -> { + Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); + anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Keyword"); + + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + addFilter(filters, "LowerCase"); + addFilter(filters, "ASCIIFolding"); + Tree wordDelimiter = addFilter(filters, "WordDelimiter"); + wordDelimiter.setProperty("preserveOriginal", "1"); + wordDelimiter.setProperty("splitOnCaseChange", "0"); + wordDelimiter.setProperty("splitOnNumerics", "0"); + wordDelimiter.setProperty("types", "types.txt"); + wordDelimiter.addChild("types.txt").addChild(JCR_CONTENT) + .setProperty(JCR_DATA, "_ => ALPHANUM\n- => ALPHANUM\n"); + }); + + Tree content = root.getTree("/").addChild("content"); + content.addChild("bar").setProperty("foo", "10022025|01.jpg"); + content.addChild("baz").setProperty("foo", "10022025_01.jpg"); + content.addChild("bat").setProperty("foo", "10022025-01.jpg"); + content.addChild("bax").setProperty("foo", "10022025_0101.jpg"); + root.commit(); + + assertEventually(() -> { + assertQuery("select * from [nt:base] where CONTAINS(*, '10022025')", List.of("/content/bar")); + assertQuery("select * from [nt:base] where CONTAINS(*, '01')", List.of("/content/bar")); + assertQuery("select * from [nt:base] where CONTAINS(*, '10022025_01*.jpg')", List.of("/content/baz", "/content/bax")); + }); + } + @Test public void fulltextSearchWithStemmingAndAsciiFilter() throws Exception { setup(List.of("foo"), idx -> { @@ -547,6 +600,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); addFilter(filters, "LowerCase"); addFilter(filters, "ASCIIFolding"); Tree wordDelimiter = addFilter(filters, "WordDelimiter"); @@ -583,7 +637,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree edgeNGram = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "NGram"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree edgeNGram = addFilter(filters, "NGram"); edgeNGram.setProperty("minGramSize", "2"); edgeNGram.setProperty("maxGramSize", "3"); }); @@ -605,7 +661,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree edgeNGram = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "EdgeNGram"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree edgeNGram = addFilter(filters, "EdgeNGram"); edgeNGram.setProperty("minGramSize", "1"); edgeNGram.setProperty("maxGramSize", "3"); }); @@ -624,7 +682,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree elision = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Elision"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree elision = addFilter(filters, "Elision"); elision.setProperty("articles", "articles.txt"); elision.addChild("articles.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "j\ns\nc\nt"); @@ -644,7 +704,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree kw = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "KeepWord"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree kw = addFilter(filters, "KeepWord"); kw.setProperty("words", "words.txt"); kw.addChild("words.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "dog\nelephant\nfox"); @@ -668,7 +730,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree length = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Length"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree length = addFilter(filters, "Length"); length.setProperty("min", "0"); length.setProperty("max", "4"); }); @@ -690,7 +754,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Whitespace"); - Tree length = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "LimitTokenCount"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree length = addFilter(filters, "LimitTokenCount"); length.setProperty("maxTokenCount", "2"); }); @@ -711,7 +777,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "GermanNormalization"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + addFilter(filters, "GermanNormalization"); }); Tree content = root.getTree("/").addChild("content"); @@ -728,7 +796,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree pcg = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "PatternCaptureGroup"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree pcg = addFilter(filters, "PatternCaptureGroup"); pcg.setProperty("pattern", "(([a-z]+)(\\d*))"); }); @@ -746,7 +816,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree shingle = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Shingle"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree shingle = addFilter(filters, "Shingle"); shingle.setProperty("minShingleSize", "2"); shingle.setProperty("maxShingleSize", "3"); shingle.setProperty("outputUnigrams", "false"); @@ -767,6 +839,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); Tree dd = addFilter(filters, "DictionaryCompoundWord"); dd.setProperty("dictionary", "words.txt"); dd.addChild("words.txt").addChild(JCR_CONTENT) @@ -792,7 +865,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { idx.setProperty(IndexConstants.ASYNC_PROPERTY_NAME, "async"); Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree synFilter = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Synonym"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree synFilter = addFilter(filters, "Synonym"); synFilter.setProperty("synonyms", "syn.txt"); // Don't add syn.txt to make analyzer (and hence index def) invalid // synFilter.addChild("syn.txt").addChild(JCR_CONTENT).setProperty(JCR_DATA, "blah, foo, bar"); @@ -814,7 +889,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree type = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Type"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree type = addFilter(filters, "Type"); type.setProperty("types", "stopTypes.txt"); type.addChild("stopTypes.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "<NUM>\n<SYNONYM>"); @@ -836,7 +913,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree type = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Type"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree type = addFilter(filters, "Type"); type.setProperty("types", "stopTypes.txt"); type.setProperty("useWhitelist", "true"); type.addChild("stopTypes.txt").addChild(JCR_CONTENT) @@ -862,7 +941,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { setup(List.of("foo"), idx -> { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree hunspellStem = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "HunspellStem"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree hunspellStem = addFilter(filters, "HunspellStem"); hunspellStem.setProperty("affix", "fr.aff"); hunspellStem.addChild("fr.aff").addChild(JCR_CONTENT) .setProperty(JCR_DATA, affix); @@ -894,6 +975,7 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); addFilter(filters, "LowerCase"); Tree elision = addFilter(filters, "Elision"); elision.setProperty("articles", "articles.txt"); @@ -918,7 +1000,9 @@ public abstract class FullTextAnalyzerCommonTest extends AbstractQueryTest { setup(List.of("foo"), idx -> { Tree anl = idx.addChild(FulltextIndexConstants.ANALYZERS).addChild(FulltextIndexConstants.ANL_DEFAULT); anl.addChild(FulltextIndexConstants.ANL_TOKENIZER).setProperty(FulltextIndexConstants.ANL_NAME, "Standard"); - Tree synFilter = addFilter(anl.addChild(FulltextIndexConstants.ANL_FILTERS), "Synonym"); + Tree filters = anl.addChild(FulltextIndexConstants.ANL_FILTERS); + filters.setOrderableChildren(true); + Tree synFilter = addFilter(filters, "Synonym"); synFilter.setProperty("synonyms", "syn.txt"); synFilter.addChild("syn.txt").addChild(JCR_CONTENT) .setProperty(JCR_DATA, "plane, airplane, aircraft\nflies=>scars");