public void collectAggregates(NodeState root, ResultCollector collector) { if (matchingType(nodeTypeName, root)) { List<Matcher> matchers = createMatchers(); collectAggregates(root, matchers, collector); } }
public boolean indexesRelativeNodes(){ for (IndexingRule r : definedRules) { if (!r.aggregate.getIncludes().isEmpty()) { return true; } } return false; }
this.propConfigs = collectPropConfigs(config, namePatterns, propIncludes, nonExistentProperties, existentProperties, nodeScopeAnalyzedProps, functionRestrictions, syncProps, similarityProperties); this.propAggregate = new Aggregate(nodeTypeName, propIncludes); this.aggregate = combine(propAggregate, nodeTypeName); this.notNullCheckEnabledProperties = ImmutableList.copyOf(existentProperties); this.similarityProperties = ImmutableList.copyOf(similarityProperties); this.fulltextEnabled = aggregate.hasNodeAggregates() || hasAnyFullTextEnabledProperty(); this.nodeFullTextIndexed = aggregate.hasNodeAggregates() || anyNodeScopeIndexedProperty(); this.propertyIndexEnabled = hasAnyPropertyIndexConfigured(); this.indexesAllNodesOfMatchingType = areAlMatchingNodeByTypeIndexed();
private static void collectAggregates(NodeState nodeState, List<Matcher> matchers, ResultCollector collector) { if (hasPatternMatcher(matchers)){ collectAggregatesForPatternMatchers(nodeState, matchers, collector); } else { collectAggregatesForDirectMatchers(nodeState, matchers, collector); } }
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); }
@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 regexAllProps() { IndexDefinitionBuilder builder = new IndexDefinitionBuilder(); builder.indexRule("nt:base").property("p"); builder.indexRule("nt:base").property("all", FulltextIndexConstants.REGEX_ALL_PROPS, true); IndexDefinition def = IndexDefinition.newBuilder(root, builder.build(), "/foo").build(); IndexingRule rule = def.getApplicableIndexingRule(root); assertNotNull(rule); PropertyDefinition pd = rule.getConfig("p"); assertNotNull(pd); assertFalse(pd.isRegexp); assertFalse(pd.relative); assertEquals(0, pd.ancestors.length); pd = rule.getConfig("all"); assertNotNull(pd); assertTrue(pd.isRegexp); assertFalse(pd.relative); assertEquals(0, pd.ancestors.length); assertThat(rule.getAggregate().getIncludes(), is(empty())); assertFalse(rule.getAggregate().hasNodeAggregates()); List<Aggregate.Matcher> matchers = rule.getAggregate() .createMatchers(new TestRoot("/")); assertThat(matchers, is(empty())); assertThat(def.getRelativeNodeNames(), is(empty())); }
@Override public void enter(NodeState before, NodeState after) { if (EmptyNodeState.MISSING_NODE == before && parent == null){ context.enableReindexMode(); } //Only check for indexing if the result is include. //In case like TRAVERSE nothing needs to be indexed for those //path if (pathFilterResult == PathFilter.Result.INCLUDE) { //For traversal in deleted sub tree before state has to be used NodeState current = after.exists() ? after : before; indexingRule = getDefinition().getApplicableIndexingRule(current); if (indexingRule != null) { currentMatchers = indexingRule.getAggregate().createMatchers(this); } } }
@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")); }
final AtomicBoolean dirtyFlag = new AtomicBoolean(); final AtomicBoolean facetFlag = new AtomicBoolean(); indexingRule.getAggregate().collectAggregates(state, new Aggregate.ResultCollector() { @Override public void onResult(Aggregate.NodeIncludeResult result) {
/** * Creates a new indexing rule base on an existing one, but for a * different node type name. * * @param original the existing rule. * @param nodeTypeName the node type name for the rule. */ IndexingRule(IndexingRule original, String nodeTypeName) { this.nodeTypeName = nodeTypeName; this.baseNodeType = original.getNodeTypeName(); this.propConfigs = original.propConfigs; this.namePatterns = original.namePatterns; this.boost = original.boost; this.inherited = original.inherited; this.propertyTypes = original.propertyTypes; this.propertyIndexEnabled = original.propertyIndexEnabled; this.propAggregate = original.propAggregate; this.nullCheckEnabledProperties = original.nullCheckEnabledProperties; this.notNullCheckEnabledProperties = original.notNullCheckEnabledProperties; this.functionRestrictions = original.functionRestrictions; this.nodeScopeAnalyzedProps = original.nodeScopeAnalyzedProps; this.aggregate = combine(propAggregate, nodeTypeName); this.fulltextEnabled = aggregate.hasNodeAggregates() || original.fulltextEnabled; this.nodeFullTextIndexed = aggregate.hasNodeAggregates() || original.nodeFullTextIndexed; this.indexesAllNodesOfMatchingType = areAlMatchingNodeByTypeIndexed(); this.nodeNameIndexed = original.nodeNameIndexed; this.syncProps = original.syncProps; this.similarityProperties = original.similarityProperties; }
public boolean isAggregated(String nodePath) { return aggregate.hasRelativeNodeInclude(nodePath); }
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 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 regexAllProps() { IndexDefinitionBuilder builder = new IndexDefinitionBuilder(); builder.indexRule("nt:base").property("p"); builder.indexRule("nt:base").property("all", FulltextIndexConstants.REGEX_ALL_PROPS, true); IndexDefinition def = IndexDefinition.newBuilder(root, builder.build(), "/foo").build(); IndexingRule rule = def.getApplicableIndexingRule(root); assertNotNull(rule); PropertyDefinition pd = rule.getConfig("p"); assertNotNull(pd); assertFalse(pd.isRegexp); assertFalse(pd.relative); assertEquals(0, pd.ancestors.length); pd = rule.getConfig("all"); assertNotNull(pd); assertTrue(pd.isRegexp); assertFalse(pd.relative); assertEquals(0, pd.ancestors.length); assertThat(rule.getAggregate().getIncludes(), is(empty())); assertFalse(rule.getAggregate().hasNodeAggregates()); List<Aggregate.Matcher> matchers = rule.getAggregate() .createMatchers(new TestRoot("/")); assertThat(matchers, is(empty())); assertThat(def.getRelativeNodeNames(), is(empty())); }
@Override public void enter(NodeState before, NodeState after) throws CommitFailedException { if (EmptyNodeState.MISSING_NODE == before && parent == null){ context.enableReindexMode(); } //Only check for indexing if the result is include. //In case like TRAVERSE nothing needs to be indexed for those //path if (pathFilterResult == PathFilter.Result.INCLUDE) { //For traversal in deleted sub tree before state has to be used NodeState current = after.exists() ? after : before; indexingRule = getDefinition().getApplicableIndexingRule(current); if (indexingRule != null) { currentMatchers = indexingRule.getAggregate().createMatchers(this); } } }
private static void matchChildren(List<Matcher> matchers, ResultCollector collector, Iterable<? extends ChildNodeEntry> children) { for (ChildNodeEntry cne : children) { List<Matcher> nextSet = newArrayListWithCapacity(matchers.size()); for (Matcher m : matchers) { Matcher result = m.match(cne.getName(), cne.getNodeState()); if (result.getStatus() == Matcher.Status.MATCH_FOUND){ result.collectResults(collector); } if (result.getStatus() != Matcher.Status.FAIL){ nextSet.addAll(result.nextSet()); } } if (!nextSet.isEmpty()) { collectAggregates(cne.getNodeState(), nextSet, collector); } } }
@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")); }
public Set<String> getRelativeNodeNames(){ //Can be computed lazily as required only for oak-run indexing for now Set<String> names = new HashSet<>(); for (IndexingRule r : definedRules) { for (Aggregate.Include i : r.aggregate.getIncludes()) { for (int d = 0; d < i.maxDepth(); d++) { if (!i.isPattern(d)) { names.add(i.getElementNameIfNotAPattern(d)); } } } } return names; }
@Override public void enter(NodeState before, NodeState after) throws CommitFailedException { if (EmptyNodeState.MISSING_NODE == before && parent == null){ context.enableReindexMode(); } //Only check for indexing if the result is include. //In case like TRAVERSE nothing needs to be indexed for those //path if (pathFilterResult == PathFilter.Result.INCLUDE) { //For traversal in deleted sub tree before state has to be used NodeState current = after.exists() ? after : before; indexingRule = getDefinition().getApplicableIndexingRule(current); if (indexingRule != null) { currentMatchers = indexingRule.getAggregate().createMatchers(this); } } }