private Aggregate combine(Aggregate propAggregate, String nodeTypeName){ Aggregate nodeTypeAgg = IndexDefinition.this.getAggregate(nodeTypeName); List<Aggregate.Include> includes = newArrayList(); includes.addAll(propAggregate.getIncludes()); if (nodeTypeAgg != null){ includes.addAll(nodeTypeAgg.getIncludes()); } return new Aggregate(nodeTypeName, includes); }
this.propConfigs = collectPropConfigs(config, namePatterns, propIncludes, nonExistentProperties, existentProperties, nodeScopeAnalyzedProps, functionRestrictions, syncProps, similarityProperties); this.propAggregate = new Aggregate(nodeTypeName, propIncludes); this.aggregate = combine(propAggregate, nodeTypeName);
private Map<String, Aggregate> collectAggregates(NodeState defn) { Map<String, Aggregate> aggregateMap = newHashMap(); for (ChildNodeEntry cne : defn.getChildNode(FulltextIndexConstants.AGGREGATES).getChildNodeEntries()) { String nodeType = cne.getName(); int recursionLimit = getOptionalValue(cne.getNodeState(), FulltextIndexConstants.AGG_RECURSIVE_LIMIT, Aggregate.RECURSIVE_AGGREGATION_LIMIT_DEFAULT); List<Aggregate.Include> includes = newArrayList(); for (ChildNodeEntry include : cne.getNodeState().getChildNodeEntries()) { NodeState is = include.getNodeState(); String primaryType = is.getString(FulltextIndexConstants.AGG_PRIMARY_TYPE); String path = is.getString(FulltextIndexConstants.AGG_PATH); boolean relativeNode = getOptionalValue(is, FulltextIndexConstants.AGG_RELATIVE_NODE, false); if (path == null) { log.warn("Aggregate pattern in {} does not have required property [{}]. {} aggregate rule would " + "be ignored", this, FulltextIndexConstants.AGG_PATH, include.getName()); continue; } includes.add(new Aggregate.NodeInclude(this, primaryType, path, relativeNode)); } aggregateMap.put(nodeType, new Aggregate(nodeType, includes, recursionLimit)); } return ImmutableMap.copyOf(aggregateMap); }
@Test public void noOfChildNodeRead() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("a"))); NodeBuilder nb = newNode("nt:base"); nb.child("a"); for (int i = 0; i < 10; i++) { nb.child("a"+i); } NodeState state = nb.getNodeState(); final AtomicInteger counter = new AtomicInteger(); Iterable<? extends ChildNodeEntry> countingIterator = Iterables.transform(state.getChildNodeEntries(), new Function<ChildNodeEntry, ChildNodeEntry>() { @Override public ChildNodeEntry apply(ChildNodeEntry input) { counter.incrementAndGet(); return input; } }); NodeState mocked = spy(state); doReturn(countingIterator).when(mocked).getChildNodeEntries(); ag.collectAggregates(mocked, col); //Here at max a single call should happen for reading child nodes assertThat(counter.get(), is(lessThanOrEqualTo(1))); }
@Test public void oneLevelTypedMixin() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("mix:title","*", false))); NodeBuilder nb = newNode("nt:base"); nb.child("a").setProperty(JcrConstants.JCR_MIXINTYPES, Collections.singleton("mix:title"), Type.NAMES); nb.child("b"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(1, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a")); }
@Test public void testReaggregate() throws Exception{ //Enable relative include for all child nodes of nt:folder //So indexing would create fulltext field for each relative nodes Aggregate agFolder = new Aggregate("nt:folder", of(ni("nt:file", "*", true))); Aggregate agFile = new Aggregate("nt:file", of(ni(null, "jcr:content", true))); mapper.add("nt:file", agFile); mapper.add("nt:folder", agFolder); NodeBuilder nb = newNode("nt:folder"); nb.child("a").child("c"); createFile(nb, "b", "hello world"); createFile(nb, "c", "hello world"); agFolder.collectAggregates(nb.getNodeState(), col); assertEquals(4, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("b", "c", "b/jcr:content", "c/jcr:content")); assertEquals(2, col.nodeResults.get("b/jcr:content").size()); //Check that a result is provided for relative node 'b'. Actual node provided //is b/jcr:content assertEquals(1, col.getRelativeNodeResults("b/jcr:content", "b").size()); }
@Test public void testRelativeNodeInclude() throws Exception{ //Enable relative include for all child nodes of nt:folder //So indexing would create fulltext field for each relative nodes Aggregate agContent = new Aggregate("app:Page", of(ni(null, "jcr:content", true))); mapper.add("app:Page", agContent); NodeBuilder nb = newNode("app:Page"); nb.child("jcr:content").setProperty("foo", "bar"); agContent.collectAggregates(nb.getNodeState(), col); assertEquals(1, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("jcr:content")); assertEquals(2, col.nodeResults.get("jcr:content").size()); //Check that a result is provided for relative node 'b'. Actual node provided //is b/jcr:content assertEquals(1, col.getRelativeNodeResults("jcr:content", "jcr:content").size()); }
@Test public void recursionEnabledWithLimitCheck() throws Exception{ int limit = 5; Aggregate agFile = new Aggregate("nt:file", of(ni("*")), limit); mapper.add("nt:file", agFile); List<String> expectedPaths = Lists.newArrayList(); NodeBuilder nb = newNode("nt:file"); nb.child("a").child("c"); String path = ""; NodeBuilder fb = nb; for (int i = 0; i < limit + 2; i++){ String name = "f "+ i; path = PathUtils.concat(path, name); fb = fb.child(name); fb.setProperty(JCR_PRIMARYTYPE, "nt:file"); if (i < limit) { expectedPaths.add(path); } } expectedPaths.add("a"); agFile.collectAggregates(nb.getNodeState(), col); assertEquals(expectedPaths.size(), col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems(toArray(expectedPaths, String.class))); }
@Test public void oneLevelNamed() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("a"))); NodeBuilder nb = newNode("nt:base"); nb.child("a"); nb.child("b"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(1, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a")); }
@Test public void testReaggregateMixin() throws Exception{ //A variant of testReaggregation but using mixin //instead of normal nodetype. It abuses mix:title //and treat it like nt:file. Test check if reaggregation //works for mixins also //Enable relative include for all child nodes of nt:folder //So indexing would create fulltext field for each relative nodes Aggregate agFolder = new Aggregate("nt:folder", of(ni("mix:title", "*", true))); Aggregate agFile = new Aggregate("mix:title", of(ni(null, "jcr:content", true))); mapper.add("mix:title", agFile); mapper.add("nt:folder", agFolder); NodeBuilder nb = newNode("nt:folder"); nb.child("a").child("c"); createFileMixin(nb, "b", "hello world"); createFileMixin(nb, "c", "hello world"); agFolder.collectAggregates(nb.getNodeState(), col); assertEquals(4, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("b", "c", "b/jcr:content", "c/jcr:content")); assertEquals(2, col.nodeResults.get("b/jcr:content").size()); //Check that a result is provided for relative node 'b'. Actual node provided //is b/jcr:content assertEquals(1, col.getRelativeNodeResults("b/jcr:content", "b").size()); }
@Test public void oneLevelTyped() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("nt:resource","*", false))); NodeBuilder nb = newNode("nt:base"); nb.child("a").setProperty(JCR_PRIMARYTYPE,"nt:resource"); nb.child("b"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(1, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a")); }
@Test public void oneLevelAll() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("*"))); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(2, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "b")); }
@Test public void includeMatches() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni(null, "*", true), ni(null, "*/*", true))); assertTrue(ag.hasRelativeNodeInclude("foo")); assertTrue(ag.hasRelativeNodeInclude("foo/bar")); assertFalse(ag.hasRelativeNodeInclude("foo/bar/baz")); Aggregate ag2 = new Aggregate("nt:base", of(ni(null, "foo", true), ni(null, "foo/*", true))); assertTrue(ag2.hasRelativeNodeInclude("foo")); assertFalse(ag2.hasRelativeNodeInclude("bar")); assertTrue(ag2.hasRelativeNodeInclude("foo/bar")); assertFalse(ag2.hasRelativeNodeInclude("foo/bar/baz")); }
@Test public void multiAggregateMapping() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("*"))); Aggregate agFile = new Aggregate("nt:file", of(ni("*"), ni("*/*"))); mapper.add("nt:file", agFile); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b").setProperty(JCR_PRIMARYTYPE, "nt:file"); nb.child("b").child("b1").child("b2"); nb.child("c"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(5, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "b", "c", "b/b1", "b/b1/b2")); }
@Test public void multiLevelAll() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("*"), ni("*/*"))); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b"); nb.child("d").child("e").child("f"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(5, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "b", "d", "a/c", "d/e")); }
@Test public void multiLevelNamed() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("a"), ni("d/e"))); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b"); nb.child("d").child("e").child("f"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(2, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "d/e")); }
@Test public void recursionEnabled() throws Exception{ Aggregate agFile = new Aggregate("nt:file", of(ni("*")), 5); mapper.add("nt:file", agFile); NodeBuilder nb = newNode("nt:file"); nb.child("a").child("c"); nb.child("b").setProperty(JCR_PRIMARYTYPE, "nt:file"); nb.child("b").child("b1").child("b2"); nb.child("c"); agFile.collectAggregates(nb.getNodeState(), col); assertEquals(4, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "b", "c", "b/b1")); }
@Test public void multiLevelNamedSubAll() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("a"), ni("d/*/*"))); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b"); nb.child("d").child("e").child("f"); nb.child("d").child("e").child("f2"); nb.child("d").child("e2").child("f3"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(4, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "d/e/f", "d/e/f2", "d/e2/f3")); }
@Test public void multiLevelTyped() throws Exception{ Aggregate ag = new Aggregate("nt:base", of(ni("a"), ni("nt:resource", "d/*/*", false))); NodeBuilder nb = newNode("nt:base"); nb.child("a").child("c"); nb.child("b"); nb.child("d").child("e").child("f").setProperty(JCR_PRIMARYTYPE,"nt:resource"); nb.child("d").child("e").child("f2"); nb.child("d").child("e2").child("f3").setProperty(JCR_PRIMARYTYPE, "nt:resource"); ag.collectAggregates(nb.getNodeState(), col); assertEquals(3, col.getNodePaths().size()); assertThat(col.getNodePaths(), hasItems("a", "d/e/f", "d/e2/f3")); }