This is an automated email from the ASF dual-hosted git repository. nfsantos 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 e9bb5933ad OAK-10590 - If includedPaths and excludedPaths are specified as a String instead of array of String, interpret them as a one-element array of Strings (#1254) e9bb5933ad is described below commit e9bb5933ad3db01ad4c60e9c77d1d83d9f8e4eb7 Author: Nuno Santos <nsan...@adobe.com> AuthorDate: Thu Dec 21 17:32:14 2023 +0000 OAK-10590 - If includedPaths and excludedPaths are specified as a String instead of array of String, interpret them as a one-element array of Strings (#1254) --- .../index/progress/NodeCounterMBeanEstimator.java | 8 +- .../index/importer/JsonDeserializationTest.java | 7 +- .../oak/composite/CompositeNodeStoreQueryTest.java | 15 +- .../oak/composite/blueGreen/IndexUtils.java | 3 +- .../pipelined/PipelinedMongoDownloadTask.java | 2 +- .../oak/plugins/index/FunctionIndexCommonTest.java | 7 +- .../plugins/index/search/IndexDefinitionTest.java | 163 +++++++++++---------- .../secondary/SecondaryStoreCacheServiceTest.java | 2 +- .../jackrabbit/oak/spi/filter/PathFilter.java | 62 ++++---- .../jackrabbit/oak/spi/filter/PathFilterTest.java | 92 +++++++++--- 10 files changed, 213 insertions(+), 148 deletions(-) diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java index 54927f740d..a3d4706117 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java @@ -25,6 +25,7 @@ import java.util.Set; import org.apache.jackrabbit.guava.common.collect.Iterables; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.plugins.index.counter.jmx.NodeCounter; +import org.apache.jackrabbit.oak.spi.filter.PathFilter; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStateUtils; import org.apache.jackrabbit.oak.spi.state.NodeStore; @@ -86,14 +87,13 @@ public class NodeCounterMBeanEstimator implements NodeCountEstimator { NodeState idxState = NodeStateUtils.getNode(root, indexPath); //No include exclude specified so include all - if (!idxState.hasProperty(PROP_INCLUDED_PATHS) - && !idxState.hasProperty(PROP_EXCLUDED_PATHS)) { + if (!idxState.hasProperty(PROP_INCLUDED_PATHS) && !idxState.hasProperty(PROP_EXCLUDED_PATHS)) { includeAll = true; return; } - Iterables.addAll(includes, idxState.getStrings(PROP_INCLUDED_PATHS)); - Iterables.addAll(excludes, idxState.getStrings(PROP_EXCLUDED_PATHS)); + Iterables.addAll(includes, PathFilter.getStrings(idxState.getProperty(PROP_INCLUDED_PATHS), Set.of())); + Iterables.addAll(excludes, PathFilter.getStrings(idxState.getProperty(PROP_EXCLUDED_PATHS), Set.of())); } if (includes.isEmpty()) { diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java index e3715bb963..e92c071798 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java @@ -29,6 +29,7 @@ import org.apache.jackrabbit.oak.json.BlobSerializer; import org.apache.jackrabbit.oak.json.JsonDeserializer; import org.apache.jackrabbit.oak.json.JsonSerializer; import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory; +import org.apache.jackrabbit.oak.spi.filter.PathFilter; import org.apache.jackrabbit.oak.spi.state.EqualsDiff; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.spi.state.NodeState; @@ -40,7 +41,7 @@ import static org.junit.Assert.assertTrue; public class JsonDeserializationTest { @Test - public void deserialize() throws Exception{ + public void deserialize() { String json = "{\n" + " \"evaluatePathRestrictions\": true,\n" + " \"compatVersion\": 2,\n" + @@ -86,8 +87,8 @@ public class JsonDeserializationTest { tree.setProperty("evaluatePathRestrictions", true); tree.setProperty("compatVersion", 2); tree.setProperty("type", "lucene"); - tree.setProperty("includedPaths", Collections.singletonList("/content"), Type.STRINGS); - tree.setProperty("excludedPaths", Collections.singletonList("/jcr:system"), Type.STRINGS); + tree.setProperty(PathFilter.PROP_INCLUDED_PATHS, Collections.singletonList("/content"), Type.STRINGS); + tree.setProperty(PathFilter.PROP_EXCLUDED_PATHS, Collections.singletonList("/jcr:system"), Type.STRINGS); tree.setProperty("async", "async"); tree.setProperty("jcr:primaryType", "oak:QueryIndexDefinition", Type.NAME); diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java index 4f65eab8d9..b673d64bd2 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java @@ -28,8 +28,8 @@ import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COU import static org.apache.jackrabbit.oak.plugins.index.IndexUtils.createIndexDefinition; import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import javax.jcr.query.Query; @@ -51,8 +51,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import org.apache.jackrabbit.guava.common.collect.ImmutableSet; -import org.apache.jackrabbit.guava.common.collect.Lists; +import java.util.List; +import java.util.Set; /** * Tests indexing and queries when using the composite node store. @@ -70,12 +70,10 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase NodeBuilder b; NodeBuilder readOnlyBuilder = readOnlyStore.getRoot().builder(); b = createIndexDefinition(readOnlyBuilder.child(INDEX_DEFINITIONS_NAME), "foo", - true, false, ImmutableSet.of("foo"), null); - b.setProperty("excludedPaths", "/jcr:system"); + true, false, Set.of("foo"), null); NodeBuilder globalBuilder = globalStore.getRoot().builder(); b = createIndexDefinition(globalBuilder.child(INDEX_DEFINITIONS_NAME), "foo", - true, false, ImmutableSet.of("foo"), null); - b.setProperty("excludedPaths", "/jcr:system"); + true, false, Set.of("foo"), null); EditorHook hook = new EditorHook( new IndexUpdateProvider(new PropertyIndexEditorProvider().with(mip))); readOnlyStore.merge(readOnlyBuilder, hook, CommitInfo.EMPTY); @@ -184,8 +182,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase b.setProperty(TYPE_PROPERTY_NAME, LuceneIndexConstants.TYPE_LUCENE); b.setProperty(FulltextIndexConstants.COMPAT_MODE, IndexFormatVersion.V2.getVersion()); b.setProperty(IndexConstants.ASYNC_PROPERTY_NAME, - Lists.newArrayList("async", "nrt"), Type.STRINGS); - b.setProperty("excludedPaths", "/jcr:system"); + List.of("async", "nrt"), Type.STRINGS); NodeBuilder foo = b.child(FulltextIndexConstants.INDEX_RULES) .child("nt:base") .child(FulltextIndexConstants.PROP_NODE) diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java index cc4fec24dc..2bbdcc2159 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java @@ -70,7 +70,7 @@ public class IndexUtils { index.setProperty(IndexConstants.ASYNC_PROPERTY_NAME, new String[] { "async", "nrt" }); index.setProperty(FulltextIndexConstants.COST_PER_EXECUTION, cost); - // index.setProperty("excludedPaths", "/jcr:system"); +// index.setProperty(PathFilter.PROP_EXCLUDED_PATHS, "/jcr:system"); Node indexRules = index.addNode(FulltextIndexConstants.INDEX_RULES); Node ntBase = indexRules.addNode("nt:base"); Node props = ntBase.addNode(FulltextIndexConstants.PROP_NODE); @@ -99,7 +99,6 @@ public class IndexUtils { * @param xpath the xpath query * @param expectedIndex the index that is expected to be used * @param expectedResult the expected list of results - * @return the index name used */ public static void assertQueryUsesIndexAndReturns(Persistence p, String xpath, String expectedIndex, String expectedResult) throws RepositoryException { diff --git a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java index 00c5c8f792..a490d5a7a9 100644 --- a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java +++ b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java @@ -404,7 +404,7 @@ public class PipelinedMongoDownloadTask implements Callable<PipelinedMongoDownlo return Set.of(); } - // Keep only unique include paths. That is, if paths "/a/b" and "/a/b/c" are both in the list, keep only "/a/b" + // Keep only unique included paths. That is, if paths "/a/b" and "/a/b/c" are both in the list, keep only "/a/b" HashSet<String> includedPathsRoots = new HashSet<>(); for (String path : sortedIncludedPaths) { if (includedPathsRoots.stream().noneMatch(ancestor -> PathUtils.isAncestor(ancestor, path))) { diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java index 9ee0980d46..02486a597f 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java @@ -42,6 +42,7 @@ import org.apache.jackrabbit.oak.commons.junit.LogCustomizer; import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; import org.apache.jackrabbit.oak.plugins.index.search.util.IndexDefinitionBuilder; import org.apache.jackrabbit.oak.query.AbstractQueryTest; +import org.apache.jackrabbit.oak.spi.filter.PathFilter; import org.junit.Assert; import org.junit.Test; import org.slf4j.event.Level; @@ -91,7 +92,7 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { @Test public void lowerCaseLocalName() throws Exception { Tree luceneIndex = createIndex("lowerLocalName", Collections.emptySet()); - luceneIndex.setProperty("excludedPaths", + luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS, List.of("/jcr:system", "/oak:index"), Type.STRINGS); Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES) .addChild("nt:base") @@ -130,7 +131,7 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { @Test public void lengthName() throws Exception { Tree luceneIndex = createIndex("lengthName", Collections.emptySet()); - luceneIndex.setProperty("excludedPaths", + luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS, List.of("/jcr:system", "/oak:index"), Type.STRINGS); Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES) .addChild("nt:base") @@ -165,7 +166,7 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { @Test public void length() throws Exception { Tree luceneIndex = createIndex("length", Collections.emptySet()); - luceneIndex.setProperty("excludedPaths", List.of("/jcr:system", "/oak:index"), Type.STRINGS); + luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS, List.of("/jcr:system", "/oak:index"), Type.STRINGS); Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES) .addChild("nt:base") .addChild(FulltextIndexConstants.PROP_NODE) diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java index 844f368b72..da17840564 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java @@ -21,10 +21,10 @@ package org.apache.jackrabbit.oak.plugins.index.search; import java.util.Collections; import java.util.List; +import java.util.Set; import javax.jcr.PropertyType; -import org.apache.jackrabbit.guava.common.collect.ImmutableList; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.plugins.index.IndexConstants; @@ -35,12 +35,12 @@ import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.junit.Test; -import static org.apache.jackrabbit.guava.common.collect.ImmutableSet.of; import static javax.jcr.PropertyType.TYPENAME_LONG; import static javax.jcr.PropertyType.TYPENAME_STRING; import static org.apache.jackrabbit.JcrConstants.NT_BASE; import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT; import static org.apache.jackrabbit.oak.api.Type.NAMES; +import static org.apache.jackrabbit.oak.api.Type.STRING; import static org.apache.jackrabbit.oak.api.Type.STRINGS; import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME; import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_NAMES; @@ -55,6 +55,7 @@ import static org.apache.jackrabbit.oak.plugins.index.search.util.IndexHelper.ne import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; import static org.apache.jackrabbit.oak.plugins.tree.TreeConstants.OAK_CHILD_ORDER; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; @@ -62,7 +63,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; public class IndexDefinitionTest { @@ -72,13 +72,13 @@ public class IndexDefinitionTest { private final NodeBuilder builder = root.builder(); @Test - public void defaultConfig() throws Exception{ + public void defaultConfig() { IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); assertFalse(idxDefn.hasSyncPropertyDefinitions()); } @Test - public void fullTextEnabled() throws Exception{ + public void fullTextEnabled() { IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE); assertTrue("By default fulltext is enabled", idxDefn.isFullTextEnabled()); @@ -91,9 +91,9 @@ public class IndexDefinitionTest { } @Test - public void propertyTypes() throws Exception{ - builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, of(TYPENAME_LONG), STRINGS)); - builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS)); + public void propertyTypes() throws Exception { + builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, Set.of(TYPENAME_LONG), STRINGS)); + builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, Set.of("foo", "bar"), STRINGS)); builder.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false); IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE); @@ -110,10 +110,18 @@ public class IndexDefinitionTest { assertTrue(rule.getConfig("foo").skipTokenization("foo")); } + + @Test + public void queryPathsAsString() { + builder.setProperty(createProperty(IndexConstants.QUERY_PATHS, "/foo/bar", STRING)); + IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); + assertEquals(new String[]{"/foo/bar"}, idxDefn.getQueryPaths()); + } + @Test - public void propertyDefinition() throws Exception{ + public void propertyDefinition() { builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE); - builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , "bar"), STRINGS)); + builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, Set.of("foo", "bar"), STRINGS)); IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE); @@ -124,7 +132,7 @@ public class IndexDefinitionTest { } @Test - public void propertyDefinitionWithExcludes() throws Exception{ + public void propertyDefinitionWithExcludes() { builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE, PropertyType.TYPENAME_DATE); IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); IndexDefinition.IndexingRule rule = idxDefn.getApplicableIndexingRule(NT_BASE); @@ -135,7 +143,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleSanity() throws Exception{ + public void indexRuleSanity() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -159,7 +167,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleInheritance() throws Exception{ + public void indexRuleInheritance() { NodeBuilder rules = builder.child(INDEX_RULES); builder.setProperty(PROP_NAME, "testIndex"); rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0); @@ -172,7 +180,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleMixin() throws Exception{ + public void indexRuleMixin() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("mix:title"); TestUtil.child(rules, "mix:title/properties/jcr:title") @@ -185,7 +193,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleMixinInheritance() throws Exception{ + public void indexRuleMixinInheritance() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("mix:mimeType"); TestUtil.child(rules, "mix:mimeType/properties/jcr:mimeType") @@ -201,7 +209,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleInheritanceDisabled() throws Exception{ + public void indexRuleInheritanceDisabled() { NodeBuilder rules = builder.child(INDEX_RULES); builder.setProperty(PROP_NAME, "testIndex"); rules.child("nt:hierarchyNode") @@ -217,9 +225,9 @@ public class IndexDefinitionTest { } @Test - public void indexRuleInheritanceOrdering() throws Exception{ + public void indexRuleInheritanceOrdering() { NodeBuilder rules = builder.child(INDEX_RULES); - rules.setProperty(OAK_CHILD_ORDER, ImmutableList.of("nt:hierarchyNode", "nt:base"),NAMES); + rules.setProperty(OAK_CHILD_ORDER, List.of("nt:hierarchyNode", "nt:base"), NAMES); rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0); rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0); @@ -229,10 +237,11 @@ public class IndexDefinitionTest { assertEquals(2.0, getRule(defn, "nt:hierarchyNode").boost, 0); assertEquals(3.0, getRule(defn, "nt:query").boost, 0); } + @Test - public void indexRuleInheritanceOrdering2() throws Exception{ + public void indexRuleInheritanceOrdering2() { NodeBuilder rules = builder.child(INDEX_RULES); - rules.setProperty(OAK_CHILD_ORDER, ImmutableList.of("nt:base", "nt:hierarchyNode"),NAMES); + rules.setProperty(OAK_CHILD_ORDER, List.of("nt:base", "nt:hierarchyNode"), NAMES); rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0); rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 3.0); @@ -245,7 +254,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleWithPropertyRegEx() throws Exception{ + public void indexRuleWithPropertyRegEx() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -269,7 +278,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleWithPropertyRegEx2() throws Exception{ + public void indexRuleWithPropertyRegEx2() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -295,7 +304,7 @@ public class IndexDefinitionTest { } @Test - public void indexRuleWithPropertyOrdering() throws Exception{ + public void indexRuleWithPropertyOrdering() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -307,7 +316,7 @@ public class IndexDefinitionTest { .setProperty(FulltextIndexConstants.PROP_IS_REGEX, true) .setProperty(FulltextIndexConstants.FIELD_BOOST, 4.0); - rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, ImmutableList.of("prop2", "prop1"), NAMES); + rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, List.of("prop2", "prop1"), NAMES); IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo"); @@ -323,14 +332,14 @@ public class IndexDefinitionTest { assertEquals(4.0f, rule1.getConfig("fooProp").boost, 0); //Order it correctly to get expected result - rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, ImmutableList.of("prop1", "prop2"), NAMES); + rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, List.of("prop1", "prop2"), NAMES); defn = new IndexDefinition(root, builder.getNodeState(), "/foo"); rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder"))); assertEquals(3.0f, rule1.getConfig("fooProp").boost, 0); } @Test - public void propertyConfigCaseInsensitive() throws Exception{ + public void propertyConfigCaseInsensitive() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/foo") @@ -353,7 +362,7 @@ public class IndexDefinitionTest { } @Test - public void skipTokenization() throws Exception{ + public void skipTokenization() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop2") @@ -369,9 +378,9 @@ public class IndexDefinitionTest { } @Test - public void formatUpdate() throws Exception{ + public void formatUpdate() { NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of(TYPENAME_STRING), of("foo", "Bar"), "async"); + "lucene", Set.of(TYPENAME_STRING), Set.of("foo", "Bar"), "async"); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertTrue(defn.isOfOldFormat()); @@ -386,9 +395,9 @@ public class IndexDefinitionTest { } @Test - public void propertyRegExAndRelativeProperty() throws Exception{ + public void propertyRegExAndRelativeProperty() { NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of(TYPENAME_STRING), of("foo"), "async"); + "lucene", Set.of(TYPENAME_STRING), Set.of("foo"), "async"); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertTrue(defn.isOfOldFormat()); @@ -401,9 +410,9 @@ public class IndexDefinitionTest { } @Test - public void fulltextEnabledAndAggregate() throws Exception{ + public void fulltextEnabledAndAggregate() { NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of("foo"), "async"); + "lucene", Set.of("foo"), "async"); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertFalse(defn.isFullTextEnabled()); @@ -416,9 +425,9 @@ public class IndexDefinitionTest { } @Test - public void costConfig() throws Exception { + public void costConfig() { NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of("foo"), "async"); + "lucene", Set.of("foo"), "async"); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertEquals(1.0, defn.getCostPerEntry(), 0); assertEquals(1.0, defn.getCostPerExecution(), 0); @@ -436,9 +445,9 @@ public class IndexDefinitionTest { } @Test - public void fulltextCost() throws Exception{ + public void fulltextCost() { NodeBuilder defnb = newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of("foo"), "async"); + "lucene", Set.of("foo"), "async"); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertEquals(300, defn.getFulltextEntryCount(300)); assertEquals(IndexDefinition.DEFAULT_ENTRY_COUNT + 100, @@ -452,9 +461,9 @@ public class IndexDefinitionTest { } @Test - public void customTikaConfig() throws Exception{ + public void customTikaConfig() { NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of(TYPENAME_STRING)); + "lucene", Set.of(TYPENAME_STRING)); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertFalse(defn.hasCustomTikaConfig()); @@ -467,13 +476,13 @@ public class IndexDefinitionTest { } @Test - public void customTikaMimeTypes() throws Exception{ + public void customTikaMimeTypes() { NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of(TYPENAME_STRING)); + "lucene", Set.of(TYPENAME_STRING)); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertEquals("application/test", defn.getTikaMappedMimeType("application/test")); - NodeBuilder app =defnb.child(FulltextIndexConstants.TIKA) + NodeBuilder app = defnb.child(FulltextIndexConstants.TIKA) .child(FulltextIndexConstants.TIKA_MIME_TYPES) .child("application"); app.child("test").setProperty(FulltextIndexConstants.TIKA_MAPPED_TYPE, "text/plain"); @@ -485,9 +494,9 @@ public class IndexDefinitionTest { } @Test - public void maxExtractLength() throws Exception{ + public void maxExtractLength() { NodeBuilder defnb = newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", - "lucene", of(TYPENAME_STRING)); + "lucene", Set.of(TYPENAME_STRING)); IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), "/foo"); assertEquals(-IndexDefinition.DEFAULT_MAX_EXTRACT_LENGTH * IndexDefinition.DEFAULT_MAX_FIELD_LENGTH, defn.getMaxExtractLength()); @@ -500,13 +509,13 @@ public class IndexDefinitionTest { } @Test(expected = IllegalStateException.class) - public void nullCheckEnabledWithNtBase() throws Exception{ + public void nullCheckEnabledWithNtBase() { builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED, true); IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); } @Test(expected = IllegalStateException.class) - public void nullCheckEnabledWithRegex() throws Exception{ + public void nullCheckEnabledWithRegex() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child(TestUtil.NT_TEST); TestUtil.child(rules, "oak:TestNode/properties/prop2") @@ -518,7 +527,7 @@ public class IndexDefinitionTest { } @Test - public void nullCheckEnabledWithTestNode() throws Exception{ + public void nullCheckEnabledWithTestNode() { NodeBuilder rules = builder.child(INDEX_RULES); TestUtil.child(rules, "oak:TestNode/properties/prop2") .setProperty(PROP_NAME, "foo") @@ -529,7 +538,7 @@ public class IndexDefinitionTest { } @Test - public void notNullCheckEnabledWithTestNode() throws Exception{ + public void notNullCheckEnabledWithTestNode() { NodeBuilder rules = builder.child(INDEX_RULES); TestUtil.child(rules, "oak:TestNode/properties/prop2") .setProperty(PROP_NAME, "foo") @@ -541,7 +550,7 @@ public class IndexDefinitionTest { //OAK-2477 @Test - public void testSuggestFrequency() throws Exception { + public void testSuggestFrequency() { int suggestFreq = 40; //default config NodeBuilder indexRoot = builder; @@ -571,7 +580,7 @@ public class IndexDefinitionTest { //OAK-2477 @Test - public void testSuggestAnalyzed() throws Exception { + public void testSuggestAnalyzed() { //default config NodeBuilder indexRoot = builder; IndexDefinition idxDefn = new IndexDefinition(root, indexRoot.getNodeState(), "/foo"); @@ -598,7 +607,7 @@ public class IndexDefinitionTest { } @Test - public void testSuggestEnabledOnNamedProp() throws Exception { + public void testSuggestEnabledOnNamedProp() { NodeBuilder rules = builder.child(INDEX_RULES); TestUtil.child(rules, "oak:TestNode/properties/prop2") .setProperty(PROP_NAME, "foo") @@ -609,7 +618,7 @@ public class IndexDefinitionTest { } @Test - public void testSuggestEnabledOnRegexProp() throws Exception { + public void testSuggestEnabledOnRegexProp() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child(TestUtil.NT_TEST); TestUtil.child(rules, "oak:TestNode/properties/prop2") @@ -622,7 +631,7 @@ public class IndexDefinitionTest { } @Test - public void testSuggestDisabled() throws Exception { + public void testSuggestDisabled() { NodeBuilder rules = builder.child(INDEX_RULES); TestUtil.child(rules, "oak:TestNode/properties/prop2") .setProperty(PROP_NAME, "foo"); @@ -632,7 +641,7 @@ public class IndexDefinitionTest { } @Test - public void analyzedEnabledForBoostedField() throws Exception { + public void analyzedEnabledForBoostedField() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -659,7 +668,7 @@ public class IndexDefinitionTest { } @Test - public void nodeFullTextIndexed_Regex() throws Exception { + public void nodeFullTextIndexed_Regex() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -681,7 +690,7 @@ public class IndexDefinitionTest { } @Test - public void nodeFullTextIndexed_Simple() throws Exception { + public void nodeFullTextIndexed_Simple() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -702,7 +711,7 @@ public class IndexDefinitionTest { } @Test - public void nodeFullTextIndexed_Aggregates() throws Exception { + public void nodeFullTextIndexed_Aggregates() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -721,7 +730,7 @@ public class IndexDefinitionTest { } @Test - public void nonIndexPropShouldHaveAllOtherConfigDisabled() throws Exception{ + public void nonIndexPropShouldHaveAllOtherConfigDisabled() { NodeBuilder rules = builder.child(INDEX_RULES); rules.child("nt:folder"); TestUtil.child(rules, "nt:folder/properties/prop1") @@ -754,38 +763,38 @@ public class IndexDefinitionTest { } @Test - public void costPerEntry() throws Exception{ + public void costPerEntry() { builder.setProperty(FulltextIndexConstants.COMPAT_MODE, 2); IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo"); assertEquals(1.0, defn.getCostPerEntry(), 0.0); } @Test - public void sync() throws Exception{ + public void sync() throws Exception { TestUtil.enableIndexingMode(builder, IndexingMode.SYNC); IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); assertTrue(idxDefn.isSyncIndexingEnabled()); } @Test - public void hasPersistedIndex() throws Exception{ + public void hasPersistedIndex() { assertFalse(IndexDefinition.hasPersistedIndex(builder.getNodeState())); builder.child(":status"); assertTrue(IndexDefinition.hasPersistedIndex(builder.getNodeState())); } @Test - public void uniqueIdForFreshIndex() throws Exception{ + public void uniqueIdForFreshIndex() { IndexDefinition defn = IndexDefinition.newBuilder(root, builder.getNodeState(), "/foo").build(); assertEquals("0", defn.getUniqueId()); builder.child(":status"); - defn = IndexDefinition.newBuilder(root, builder.getNodeState(),"/foo").build(); + defn = IndexDefinition.newBuilder(root, builder.getNodeState(), "/foo").build(); assertNull(defn.getUniqueId()); } @Test - public void nodeTypeChange() throws Exception{ + public void nodeTypeChange() { IndexDefinition defn = IndexDefinition.newBuilder(root, builder.getNodeState(), "/foo").build(); NodeBuilder b2 = root.builder(); TestUtil.registerNodeType(b2, TestUtil.TEST_NODE_TYPE); @@ -801,7 +810,7 @@ public class IndexDefinitionTest { } @Test - public void uniqueIsSync() throws Exception{ + public void uniqueIsSync() { IndexDefinitionBuilder defnb = new IndexDefinitionBuilder(); defnb.indexRule("nt:base").property("foo").unique(); @@ -812,7 +821,7 @@ public class IndexDefinitionTest { } @Test - public void syncIsProperty() throws Exception{ + public void syncIsProperty() { IndexDefinitionBuilder defnb = new IndexDefinitionBuilder(); defnb.indexRule("nt:base").property("foo").sync(); @@ -822,7 +831,7 @@ public class IndexDefinitionTest { } @Test - public void syncPropertyDefinitions() throws Exception{ + public void syncPropertyDefinitions() { IndexDefinitionBuilder defnb = new IndexDefinitionBuilder(); defnb.indexRule("nt:base").property("foo").sync(); @@ -846,7 +855,7 @@ public class IndexDefinitionTest { "- * (UNDEFINED) multiple"; @Test - public void nodeTypeIndexed() throws Exception{ + public void nodeTypeIndexed() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -872,7 +881,7 @@ public class IndexDefinitionTest { } @Test - public void nodeTypeIndexedSync() throws Exception{ + public void nodeTypeIndexedSync() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -894,7 +903,7 @@ public class IndexDefinitionTest { } @Test - public void nodeTypeIndexed_IgnoreOtherProps() throws Exception{ + public void nodeTypeIndexed_IgnoreOtherProps() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -915,7 +924,7 @@ public class IndexDefinitionTest { } @Test - public void nodeTypeIndexed_IgnoreAggregates() throws Exception{ + public void nodeTypeIndexed_IgnoreAggregates() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -937,7 +946,7 @@ public class IndexDefinitionTest { } @Test - public void nodeTypeIndex_mixin() throws Exception{ + public void nodeTypeIndex_mixin() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -960,7 +969,7 @@ public class IndexDefinitionTest { } @Test - public void mixinAndPrimaryType() throws Exception{ + public void mixinAndPrimaryType() { TestUtil.registerNodeType(builder, testNodeTypeDefn); root = builder.getNodeState(); @@ -1049,21 +1058,21 @@ public class IndexDefinitionTest { //TODO indexesAllNodesOfMatchingType - with nullCheckEnabled - private static IndexingRule getRule(IndexDefinition defn, String typeName){ + private static IndexingRule getRule(IndexDefinition defn, String typeName) { return defn.getApplicableIndexingRule(asState(newNode(typeName))); } - private static NodeState asState(NodeBuilder nb){ + private static NodeState asState(NodeBuilder nb) { return nb.getNodeState(); } - private static NodeBuilder newNode(String typeName){ + private static NodeBuilder newNode(String typeName) { NodeBuilder builder = EMPTY_NODE.builder(); builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME); return builder; } - private static NodeBuilder newNode(String typeName, String mixins){ + private static NodeBuilder newNode(String typeName, String mixins) { NodeBuilder builder = EMPTY_NODE.builder(); builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName); builder.setProperty(JcrConstants.JCR_MIXINTYPES, Collections.singleton(mixins), Type.NAMES); diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java index 925f105d8f..d3956873e6 100644 --- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java +++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java @@ -99,7 +99,7 @@ public class SecondaryStoreCacheServiceTest { @Test public void configurePathFilter() throws Exception{ Map<String, Object> config = new HashMap<>(); - config.put("includedPaths", new String[] {"/a"}); + config.put(PathFilter.PROP_INCLUDED_PATHS, new String[] {"/a"}); MockOsgi.activate(cacheService, context.bundleContext(), config); assertEquals(PathFilter.Result.INCLUDE, cacheService.getPathFilter().filter("/a")); diff --git a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java index 71be083b24..f3d1ef6aba 100644 --- a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java +++ b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java @@ -21,8 +21,6 @@ package org.apache.jackrabbit.oak.spi.filter; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Set; @@ -34,7 +32,6 @@ import org.jetbrains.annotations.NotNull; import static org.apache.jackrabbit.guava.common.base.Preconditions.checkState; import static org.apache.jackrabbit.guava.common.collect.Sets.newHashSet; -import static java.util.Collections.singletonList; import static org.apache.jackrabbit.oak.commons.PathUtils.isAncestor; /** @@ -42,7 +39,7 @@ import static org.apache.jackrabbit.oak.commons.PathUtils.isAncestor; * or not */ public class PathFilter { - private static final Collection<String> INCLUDE_ROOT = singletonList("/"); + private static final Set<String> INCLUDE_ROOT = Set.of("/"); /** * Multi value property name used to determine list of paths to be included */ @@ -73,38 +70,53 @@ public class PathFilter { TRAVERSE } - private static final PathFilter ALL = new PathFilter(INCLUDE_ROOT, Collections.emptyList()) { + private static final PathFilter ALL = new PathFilter(INCLUDE_ROOT, List.of()) { @Override public Result filter(@NotNull String path) { return Result.INCLUDE; } }; - private final String[] includedPaths; - private final String[] excludedPaths; /** * Constructs the predicate based on given definition state. It looks for * multi value property with names {@link PathFilter#PROP_INCLUDED_PATHS} * and {@link PathFilter#PROP_EXCLUDED_PATHS}. Both the properties are * optional. - * + * If the properties are defined as String instead of Strings, then they + * are interpreted as a single-element list. + * * @param defn nodestate representing the configuration. Generally it would - * be the nodestate representing the index definition + * be the nodestate representing the index definition * @return predicate based on the passed definition state */ public static PathFilter from(@NotNull NodeBuilder defn) { - if (!defn.hasProperty(PROP_EXCLUDED_PATHS) && - !defn.hasProperty(PROP_INCLUDED_PATHS)) { + if (!defn.hasProperty(PROP_EXCLUDED_PATHS) && !defn.hasProperty(PROP_INCLUDED_PATHS)) { return ALL; } - return new PathFilter(getStrings(defn, PROP_INCLUDED_PATHS, - INCLUDE_ROOT), getStrings(defn, PROP_EXCLUDED_PATHS, - Collections.emptyList())); + return new PathFilter( + getStrings(defn.getProperty(PROP_INCLUDED_PATHS), INCLUDE_ROOT), + getStrings(defn.getProperty(PROP_EXCLUDED_PATHS), Set.of()) + ); + } + + /* + * Gets the value of the given property as a set of strings. This works both if the property is of type STRING or + * type STRINGS. If the type is STRING, then it is interpreted as a single-element list. This is the default behavior + * of calling {@link PropertyState#getValue(Type)} with {@link Type#STRINGS}. + */ + public static Iterable<String> getStrings(PropertyState ps, Set<String> defaultValues) { + if (ps != null && (ps.getType() == Type.STRING || ps.getType() == Type.STRINGS)) { + return ps.getValue(Type.STRINGS); + } + return defaultValues; } + private final String[] includedPaths; + private final String[] excludedPaths; + /** * Constructs the predicate with given included and excluded paths - * + * <p> * If both are empty then all paths would be considered to be included * * @param includes list of paths which should be included @@ -116,8 +128,8 @@ public class PathFilter { PathUtils.unifyInExcludes(includeCopy, excludeCopy); checkState(!includeCopy.isEmpty(), "No valid include provided. Includes %s, " + "Excludes %s", includes, excludes); - this.includedPaths = includeCopy.toArray(new String[includeCopy.size()]); - this.excludedPaths = excludeCopy.toArray(new String[excludeCopy.size()]); + this.includedPaths = includeCopy.toArray(new String[0]); + this.excludedPaths = excludeCopy.toArray(new String[0]); } /** @@ -164,26 +176,15 @@ public class PathFilter { '}'; } - private static Iterable<String> getStrings(NodeBuilder builder, String propertyName, - Collection<String> defaultVal) { - PropertyState property = builder.getProperty(propertyName); - if (property != null && property.getType() == Type.STRINGS) { - return property.getValue(Type.STRINGS); - } else { - return defaultVal; - } - } - /** * Check whether this node and all descendants are included in this filter. - * + * * @param path the path * @return true if this and all descendants of this path are included in the filter */ public boolean areAllDescendantsIncluded(String path) { for (String excludedPath : excludedPaths) { - if (excludedPath.equals(path) || isAncestor(excludedPath, path) || - isAncestor(path, excludedPath)) { + if (excludedPath.equals(path) || isAncestor(excludedPath, path) || isAncestor(path, excludedPath)) { return false; } } @@ -194,5 +195,4 @@ public class PathFilter { } return false; } - } diff --git a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java index 315e93cdf9..37c62ecea0 100644 --- a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java +++ b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java @@ -19,13 +19,14 @@ package org.apache.jackrabbit.oak.spi.filter; -import java.util.Collections; - import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.jetbrains.annotations.NotNull; import org.junit.Test; -import static org.apache.jackrabbit.guava.common.collect.ImmutableList.of; +import java.util.HashSet; +import java.util.Set; + import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; import static org.apache.jackrabbit.oak.spi.filter.PathFilter.PROP_EXCLUDED_PATHS; @@ -36,8 +37,8 @@ import static org.junit.Assert.fail; public class PathFilterTest { @Test - public void exclude() throws Exception { - PathFilter p = new PathFilter(of("/"), of("/etc")); + public void exclude() { + PathFilter p = new PathFilter(Set.of("/"), Set.of("/etc")); assertEquals(PathFilter.Result.INCLUDE, p.filter("/")); assertEquals(PathFilter.Result.INCLUDE, p.filter("/a")); assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc")); @@ -45,8 +46,8 @@ public class PathFilterTest { } @Test - public void include() throws Exception { - PathFilter p = new PathFilter(of("/content", "/etc"), of("/etc/workflow/instance")); + public void include() { + PathFilter p = new PathFilter(Set.of("/content", "/etc"), Set.of("/etc/workflow/instance")); assertEquals(PathFilter.Result.TRAVERSE, p.filter("/")); assertEquals(PathFilter.Result.EXCLUDE, p.filter("/var")); assertEquals(PathFilter.Result.INCLUDE, p.filter("/content")); @@ -61,7 +62,7 @@ public class PathFilterTest { } @Test - public void emptyConfig() throws Exception { + public void emptyConfig() { NodeBuilder root = EMPTY_NODE.builder(); PathFilter p = PathFilter.from(root); assertEquals(PathFilter.Result.INCLUDE, p.filter("/")); @@ -69,10 +70,10 @@ public class PathFilterTest { } @Test - public void config() throws Exception { + public void config() { NodeBuilder root = EMPTY_NODE.builder(); - root.setProperty(createProperty(PROP_INCLUDED_PATHS, of("/etc"), Type.STRINGS)); - root.setProperty(createProperty(PROP_EXCLUDED_PATHS, of("/etc/workflow"), Type.STRINGS)); + root.setProperty(createProperty(PROP_INCLUDED_PATHS, Set.of("/etc"), Type.STRINGS)); + root.setProperty(createProperty(PROP_EXCLUDED_PATHS, Set.of("/etc/workflow"), Type.STRINGS)); PathFilter p = PathFilter.from(root); assertEquals(PathFilter.Result.TRAVERSE, p.filter("/")); assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc")); @@ -82,9 +83,22 @@ public class PathFilterTest { } @Test - public void configOnlyExclude() throws Exception { + public void configWithStringProperties() { NodeBuilder root = EMPTY_NODE.builder(); - root.setProperty(createProperty(PROP_EXCLUDED_PATHS, of("/etc/workflow"), Type.STRINGS)); + root.setProperty(createProperty(PROP_INCLUDED_PATHS, "/etc", Type.STRING)); + root.setProperty(createProperty(PROP_EXCLUDED_PATHS, "/etc/workflow", Type.STRING)); + PathFilter p = PathFilter.from(root); + assertEquals(PathFilter.Result.TRAVERSE, p.filter("/")); + assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc")); + assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc/a")); + assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc/workflow")); + assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc/workflow/1")); + } + + @Test + public void configOnlyExclude() { + NodeBuilder root = EMPTY_NODE.builder(); + root.setProperty(createProperty(PROP_EXCLUDED_PATHS, Set.of("/etc/workflow"), Type.STRINGS)); PathFilter p = PathFilter.from(root); assertEquals(PathFilter.Result.INCLUDE, p.filter("/")); assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc")); @@ -94,26 +108,70 @@ public class PathFilterTest { } @Test - public void invalid() throws Exception { + public void invalid() { try { - new PathFilter(Collections.<String>emptyList(), of("/etc")); + new PathFilter(Set.of(), Set.of("/etc")); fail(); } catch (IllegalStateException ignore) { // expected } try { - new PathFilter(of("/etc/workflow"), of("/etc")); + new PathFilter(Set.of("/etc/workflow"), Set.of("/etc")); fail(); } catch (IllegalStateException ignore) { // expected } try { - new PathFilter(Collections.<String>emptyList(), Collections.<String>emptyList()); + new PathFilter(Set.of(), Set.of()); fail(); } catch (IllegalStateException ignore) { // expected } } + + @Test + public void getStringsLenientNodeBuilder_MultipleValues() { + NodeBuilder root = EMPTY_NODE.builder(); + @NotNull NodeBuilder b1 = root.setProperty(createProperty("propMultiple", Set.of("/p1", "/p2"), Type.STRINGS)); + assertEquals(Set.of("/p1", "/p2"), toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), Set.of("default")))); + } + + @Test + public void getStringsLenientNodeBuilder_SingleValueAsSet() { + NodeBuilder root = EMPTY_NODE.builder(); + @NotNull NodeBuilder b1 = root.setProperty(createProperty("propMultiple", Set.of("/p1"), Type.STRINGS)); + assertEquals(Set.of("/p1"), toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), Set.of("default")))); + } + + @Test + public void getStringsLenientNodeBuilder_SingleValueAsString() { + NodeBuilder root = EMPTY_NODE.builder(); + @NotNull NodeBuilder b1 = root.setProperty(createProperty("propMultiple", "/p1", Type.STRING)); + assertEquals(Set.of("/p1"), toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), Set.of("default")))); + } + + @Test + public void getStringsLenientNodeBuilder_NoValue() { + NodeBuilder root = EMPTY_NODE.builder(); + assertEquals(Set.of("default"), toSet(PathFilter.getStrings(root.getProperty("propMultiple"), Set.of("default")))); + } + + @Test + public void getStringsLenientNodeBuilder_WrongType() { + NodeBuilder root = EMPTY_NODE.builder(); + @NotNull NodeBuilder b1 = root.setProperty(createProperty("propMultiple", 1L, Type.LONG)); + assertEquals(Set.of("default"), toSet(PathFilter.getStrings(root.getProperty("propMultiple"), Set.of("default")))); + } + + static private <T> Set<T> toSet(Iterable<T> iterable) { + HashSet<T> set = new HashSet<>(); + for (T t : iterable) { + set.add(t); + } + return set; + } + + }