Skip to content

Commit

Permalink
HSEARCH-3136 Track the encountered paths and useless includePaths in …
Browse files Browse the repository at this point in the history
…ConfiguredIndexSchemaNestingContext
  • Loading branch information
yrodiere committed Mar 21, 2019
1 parent 7649c90 commit d5122d4
Show file tree
Hide file tree
Showing 3 changed files with 369 additions and 16 deletions.
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.search.engine.mapper.mapping.building.impl;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -91,6 +93,12 @@ public <T> Optional<T> addIndexedEmbeddedIfIncluded(
while ( nextDotIndex >= 0 ) {
String objectName = prefixToParse.substring( afterPreviousDotIndex, nextDotIndex );
contextBuilder.appendObject( objectName );

// Make sure to mark the paths as encountered in the filter
String objectNameRelativeToFilter = prefixToParse.substring( 0, nextDotIndex );
// We only use isPathIncluded for its side effect: it marks the path as encountered
filter.isPathIncluded( objectNameRelativeToFilter );

afterPreviousDotIndex = nextDotIndex + 1;
nextDotIndex = prefixToParse.indexOf( '.', afterPreviousDotIndex );
}
Expand All @@ -105,6 +113,24 @@ public <T> Optional<T> addIndexedEmbeddedIfIncluded(
}
}

public Set<String> getUselessIncludePaths() {
Set<String> includePaths = filter.getProperExplicitlyIncludedPaths();
Map<String, Boolean> encounteredFieldPaths = filter.getEncounteredFieldPaths();
Set<String> uselessIncludePaths = new LinkedHashSet<>();
for ( String path : includePaths ) {
Boolean included = encounteredFieldPaths.get( path );
if ( included == null /* not encountered */ || !included ) {
// An "includePaths" filter that does not result in inclusion is useless
uselessIncludePaths.add( path );
}
}
return uselessIncludePaths;
}

public Set<String> getEncounteredFieldPaths() {
return filter.getEncounteredFieldPaths().keySet();
}

public interface NestedContextBuilder<T> {

void appendObject(String objectName);
Expand Down
Expand Up @@ -9,6 +9,9 @@
import java.lang.invoke.MethodHandles;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.hibernate.search.engine.logging.impl.Log;
Expand Down Expand Up @@ -67,7 +70,8 @@ class IndexSchemaFilter {
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private static final IndexSchemaFilter ROOT = new IndexSchemaFilter(
null, null, null, null, Collections.emptySet()
null, null, null,
null, Collections.emptySet(), Collections.emptySet()
);

public static IndexSchemaFilter root() {
Expand All @@ -92,13 +96,27 @@ public static IndexSchemaFilter root() {
*/
private final Set<String> explicitlyIncludedPaths;

/**
* The {@code explicitlyIncludedPaths} that were included by this filter explicitly (not a parent filter).
*/
private final Set<String> properExplicitlyIncludedPaths;

/**
* The {@code paths} that were encountered, i.e. passed to {@link #isPathIncluded(String)}
* or to the same method of a child filter.
*/
// Use a LinkedHashSet, since the set will be exposed through a getter and may be iterated on
private final Map<String, Boolean> encounteredFieldPaths = new LinkedHashMap<>();

private IndexSchemaFilter(IndexSchemaFilter parent, MappableTypeModel parentTypeModel, String relativePrefix,
Integer remainingCompositionDepth, Set<String> explicitlyIncludedPaths) {
Integer remainingCompositionDepth, Set<String> explicitlyIncludedPaths,
Set<String> properExplicitlyIncludedPaths) {
this.parent = parent;
this.parentTypeModel = parentTypeModel;
this.relativePrefix = relativePrefix;
this.remainingCompositionDepth = remainingCompositionDepth;
this.explicitlyIncludedPaths = explicitlyIncludedPaths;
this.properExplicitlyIncludedPaths = properExplicitlyIncludedPaths;
}

@Override
Expand All @@ -114,13 +132,30 @@ public String toString() {
}

public boolean isPathIncluded(String relativePath) {
return isPathIncluded( remainingCompositionDepth, explicitlyIncludedPaths, relativePath );
boolean included = isPathIncluded( remainingCompositionDepth, explicitlyIncludedPaths, relativePath );
markAsEncountered( relativePath, included );
return included;
}

private void markAsEncountered(String relativePath, boolean included) {
encounteredFieldPaths.put( relativePath, included );
if ( parent != null ) {
parent.markAsEncountered( relativePrefix + relativePath, included );
}
}

public boolean isEveryPathExcluded() {
return !isEveryPathIncludedByDefault( remainingCompositionDepth ) && !isAnyPathExplicitlyIncluded();
}

public Set<String> getProperExplicitlyIncludedPaths() {
return properExplicitlyIncludedPaths;
}

public Map<String, Boolean> getEncounteredFieldPaths() {
return encounteredFieldPaths;
}

private String getPathFromSameIndexedEmbeddedSinceNoCompositionLimits(MappableTypeModel parentTypeModel, String relativePrefix) {
if ( hasCompositionLimits() ) {
return null;
Expand Down Expand Up @@ -184,26 +219,20 @@ public IndexSchemaFilter composeWithNested(MappableTypeModel parentTypeModel, St
composedRemainingDepth = nestedRemainingDepth;
}

Set<String> composedFilterExplicitlyIncludedPaths = composeExplicitlyIncludedPaths(
relativePrefix, nullSafeIncludePaths, currentRemainingDepth, nestedRemainingDepth
);

return new IndexSchemaFilter(
this, parentTypeModel, relativePrefix,
composedRemainingDepth, composedFilterExplicitlyIncludedPaths
);
}

private Set<String> composeExplicitlyIncludedPaths(String relativePrefix, Set<String> nullSafeIncludePaths,
Integer currentRemainingDepth, Integer nestedRemainingDepth) {
// The included paths that will be used to determine inclusion
Set<String> composedFilterExplicitlyIncludedPaths = new HashSet<>();
// The subset of these included paths that were added by the nested filter (and not a parent filter)
// Use a LinkedHashSet, since the set will be exposed through a getter and may be iterated on
Set<String> composedFilterProperExplicitlyIncludedPaths = new LinkedHashSet<>();

/*
* Add the nested filter's explicitly included paths to the composed filter's "explicitlyIncludedPaths",
* provided they are not filtered out by the current filter.
*/
for ( String path : nullSafeIncludePaths ) {
if ( isPathIncluded( currentRemainingDepth, explicitlyIncludedPaths, relativePrefix + path ) ) {
composedFilterExplicitlyIncludedPaths.add( path );
composedFilterProperExplicitlyIncludedPaths.add( path );
// Also add paths leading to this path (so that object nodes are not excluded)
int afterPreviousDotIndex = 0;
int nextDotIndex = path.indexOf( '.', afterPreviousDotIndex );
Expand All @@ -228,7 +257,12 @@ private Set<String> composeExplicitlyIncludedPaths(String relativePrefix, Set<St
}
}
}
return composedFilterExplicitlyIncludedPaths;

return new IndexSchemaFilter(
this, parentTypeModel, relativePrefix,
composedRemainingDepth, composedFilterExplicitlyIncludedPaths,
composedFilterProperExplicitlyIncludedPaths
);
}

private static boolean isPathIncluded(Integer remainingDepth, Set<String> explicitlyIncludedPaths, String relativePath) {
Expand Down

0 comments on commit d5122d4

Please sign in to comment.