From 513eb8e5a624d9c09d9f051bbf59ac1ff856bdb7 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 28 Oct 2020 17:50:24 +0100 Subject: [PATCH] Refactor DOMQueryPredicate Refactor aimed at allowing composite predicates without multiple lookups. While the DOM language allows this use case, the binding layer does not take advantage of it. JIRA: MDSAL-617 Change-Id: Ib8a3f77ee660a8c2881d0a18bd0238c6ddce5ade Signed-off-by: Robert Varga --- .../query/AbstractValueMatchBuilder.java | 13 +- .../query/DefaultComparableMatchBuilder.java | 13 +- .../query/DefaultStringMatchBuilder.java | 13 +- .../dom/api/query/DOMQueryPredicate.java | 443 +++++++++++++----- .../dom/spi/query/DOMQueryEvaluator.java | 2 +- .../mdsal/dom/spi/query/DOMQueryIterator.java | 2 +- .../mdsal/dom/spi/query/DOMQueryMatcher.java | 34 +- 7 files changed, 366 insertions(+), 154 deletions(-) diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/AbstractValueMatchBuilder.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/AbstractValueMatchBuilder.java index 47a32b96bd..080447ffbd 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/AbstractValueMatchBuilder.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/AbstractValueMatchBuilder.java @@ -14,8 +14,7 @@ import org.opendaylight.mdsal.binding.api.query.ValueMatch; import org.opendaylight.mdsal.binding.api.query.ValueMatchBuilder; import org.opendaylight.mdsal.binding.dom.adapter.query.QueryBuilderState.BoundMethod; import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Exists; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.ValueEquals; +import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Match; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -35,26 +34,26 @@ abstract class AbstractValueMatchBuilder implements Val @Override public final ValueMatch nonNull() { - return withPredicate(new Exists(relativePath())); + return withMatch(Match.exists()); } @Override public final ValueMatch isNull() { - return withPredicate(new Exists(relativePath()).negate()); + return withMatch(Match.exists().negate()); } @Override public final ValueMatch valueEquals(final V value) { - return withPredicate(new ValueEquals<>(relativePath(), value)); + return withMatch(Match.valueEquals(value)); } final YangInstanceIdentifier relativePath() { return method.parentPath.node(((DataSchemaNode) method.methodCodec.getSchema()).getQName()); } - final @NonNull ValueMatch withPredicate(final DOMQueryPredicate predicate) { + final @NonNull ValueMatch withMatch(final Match match) { // FIXME: this does not quite take value codec into account :( - builder.addPredicate(predicate); + builder.addPredicate(DOMQueryPredicate.of(relativePath(), match)); return new DefaultValueMatch<>(builder, select); } } diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultComparableMatchBuilder.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultComparableMatchBuilder.java index 64f0382ba0..d76937045d 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultComparableMatchBuilder.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultComparableMatchBuilder.java @@ -10,10 +10,7 @@ package org.opendaylight.mdsal.binding.dom.adapter.query; import org.opendaylight.mdsal.binding.api.query.ComparableMatchBuilder; import org.opendaylight.mdsal.binding.api.query.ValueMatch; import org.opendaylight.mdsal.binding.dom.adapter.query.QueryBuilderState.BoundMethod; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.GreaterThan; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.GreaterThanOrEqual; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.LessThan; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.LessThanOrEqual; +import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Match; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -26,21 +23,21 @@ final class DefaultComparableMatchBuilder lessThan(final V value) { - return withPredicate(new LessThan<>(relativePath(), value)); + return withMatch(Match.lessThan(value)); } @Override public ValueMatch lessThanOrEqual(final V value) { - return withPredicate(new LessThanOrEqual<>(relativePath(), value)); + return withMatch(Match.lessThanOrEqual(value)); } @Override public ValueMatch greaterThan(final V value) { - return withPredicate(new GreaterThan<>(relativePath(), value)); + return withMatch(Match.greaterThan(value)); } @Override public ValueMatch greaterThanOrEqual(final V value) { - return withPredicate(new GreaterThanOrEqual<>(relativePath(), value)); + return withMatch(Match.greaterThanOrEqual(value)); } } diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultStringMatchBuilder.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultStringMatchBuilder.java index 73bc9a3db4..15274c06d1 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultStringMatchBuilder.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultStringMatchBuilder.java @@ -11,10 +11,7 @@ import java.util.regex.Pattern; import org.opendaylight.mdsal.binding.api.query.StringMatchBuilder; import org.opendaylight.mdsal.binding.api.query.ValueMatch; import org.opendaylight.mdsal.binding.dom.adapter.query.QueryBuilderState.BoundMethod; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Contains; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.EndsWith; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.MatchesPattern; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.StartsWith; +import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Match; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -27,21 +24,21 @@ final class DefaultStringMatchBuilder extends AbstractValu @Override public ValueMatch startsWith(final String str) { - return withPredicate(new StartsWith(relativePath(), str)); + return withMatch(Match.stringStartsWith(str)); } @Override public ValueMatch endsWith(final String str) { - return withPredicate(new EndsWith(relativePath(), str)); + return withMatch(Match.stringEndsWith(str)); } @Override public ValueMatch contains(final String str) { - return withPredicate(new Contains(relativePath(), str)); + return withMatch(Match.stringContains(str)); } @Override public ValueMatch matchesPattern(final Pattern pattern) { - return withPredicate(new MatchesPattern(relativePath(), pattern)); + return withMatch(Match.stringMatches(pattern)); } } diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryPredicate.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryPredicate.java index 80db6f3442..fd6266131b 100644 --- a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryPredicate.java +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryPredicate.java @@ -11,243 +11,470 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; -import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.collect.ImmutableList; +import java.util.Iterator; import java.util.function.Predicate; import java.util.regex.Pattern; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +/** + * A single {@link DOMQuery} predicate. It is composed of a relative path and a match. The relative path needs to be + * expanded using usual wildcard rules, i.e. NodeIdentifier being used as a 'match all' identifier. For all candidate + * nodes selected by the relative path, the corresponding match needs to be invoked. + */ @Beta -public abstract class DOMQueryPredicate implements Immutable, Predicate> { - abstract static class AbstractLeafDOMQueryPredicate extends DOMQueryPredicate { - AbstractLeafDOMQueryPredicate(final YangInstanceIdentifier relativePath) { - super(relativePath); +@NonNullByDefault +public final class DOMQueryPredicate implements Immutable { + /** + * A single match. The primary entrypoint is {@link #test(NormalizedNode)}, but during composition instances may + * be combined in a manner similar to {@link Predicate}. + */ + public abstract static class Match { + Match() { + // Hidden on purpose } - @Override - public final boolean test(final NormalizedNode data) { - return testValue(data instanceof LeafNode ? ((LeafNode) data).getValue() : null); + public static final Match exists() { + return MatchExists.INSTACE; } - abstract boolean testValue(Object data); - } + public static final > Match greaterThan(final T value) { + return new MatchGreaterThan<>(value); + } - abstract static class AbstractValueDOMQueryPredicate extends AbstractLeafDOMQueryPredicate { - private final @NonNull T value; + public static final > Match greaterThanOrEqual(final T value) { + return new MatchGreaterThanOrEqual<>(value); + } - AbstractValueDOMQueryPredicate(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath); - this.value = requireNonNull(value); + public static final > Match lessThan(final T value) { + return new MatchLessThan<>(value); } - final @NonNull T value() { - return value; + public static final > Match lessThanOrEqual(final T value) { + return new MatchLessThanOrEqual<>(value); + } + + public static final Match stringMatches(final Pattern pattern) { + return new MatchStringMatches(pattern); + } + + public static final Match stringStartsWith(final String str) { + return new MatchStringStartsWith(str); + } + + public static final Match stringEndsWith(final String str) { + return new MatchStringEndsWith(str); + } + + public static final Match stringContains(final String str) { + return new MatchStringContains(str); + } + + public static final Match valueEquals(final V value) { + return new MatchValueEquals<>(value); + } + + /** + * Return a {@link Match} which tests the opposite of this match. + * + * @return Negated match. + */ + public Match negate() { + return new MatchNot(this); + } + + public Match and(final Match other) { + return new MatchAll(ImmutableList.of(this, other)); + } + + public Match or(final Match other) { + return new MatchAny(ImmutableList.of(this, other)); + } + + public abstract boolean test(@Nullable NormalizedNode data); + + final void appendTo(final StringBuilder sb) { + sb.append(op()).append('('); + appendArgument(sb); + sb.append(')'); + } + + void appendArgument(final StringBuilder sb) { + // No-op by default } + abstract String op(); + @Override - ToStringHelper addToStringAttributes(final ToStringHelper helper) { - return helper.add("value", value); + public final String toString() { + final var sb = new StringBuilder(); + appendTo(sb); + return sb.toString(); } } - abstract static class AbstractComparableDOMQueryPredicate> - extends AbstractValueDOMQueryPredicate { - AbstractComparableDOMQueryPredicate(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchAll extends CompositeMatch { + MatchAll(final ImmutableList components) { + super(components); } @Override - @SuppressWarnings("unchecked") - public final boolean testValue(final Object data) { - return data != null && test(value().compareTo((T) data)); + public MatchAll and(final Match other) { + return new MatchAll(newComponents(other)); } - abstract boolean test(int valueToData); + @Override + public boolean test(final @Nullable NormalizedNode data) { + for (Match component : components()) { + if (!component.test(data)) { + return false; + } + } + return true; + } + + @Override + String op() { + return "allOf"; + } } - abstract static class AbstractStringDOMQueryPredicate extends AbstractValueDOMQueryPredicate { - AbstractStringDOMQueryPredicate(final YangInstanceIdentifier relativePath, final String value) { - super(relativePath, value); + private static final class MatchAny extends CompositeMatch { + MatchAny(final ImmutableList components) { + super(components); } @Override - public final boolean testValue(final Object data) { - return data instanceof String && test((String) data); + public MatchAny or(final Match other) { + return new MatchAny(newComponents(other)); } - abstract boolean test(@NonNull String str); + @Override + public boolean test(final @Nullable NormalizedNode data) { + for (Match component : components()) { + if (component.test(data)) { + return true; + } + } + return false; + } + + @Override + String op() { + return "anyOf"; + } } - public static final class Exists extends DOMQueryPredicate { - public Exists(final YangInstanceIdentifier relativePath) { - super(relativePath); + private static final class MatchExists extends Match { + static final MatchExists INSTACE = new MatchExists(); + + private MatchExists() { + // Hidden on purpose } @Override - public boolean test(final NormalizedNode data) { + public boolean test(final @Nullable NormalizedNode data) { return data != null; } + + @Override + String op() { + return "exists"; + } } - public static final class Not extends DOMQueryPredicate { - private final DOMQueryPredicate predicate; + private static final class MatchNot extends Match { + private final Match match; - Not(final DOMQueryPredicate predicate) { - super(predicate.relativePath); - this.predicate = predicate; + MatchNot(final Match match) { + this.match = requireNonNull(match); } - public @NonNull DOMQueryPredicate predicate() { - return predicate; + @Override + public Match negate() { + return match; + } + + @Override + public boolean test(final @Nullable NormalizedNode data) { + return !match.test(data); } @Override - public DOMQueryPredicate negate() { - return predicate; + String op() { + return "not"; } @Override - public boolean test(final NormalizedNode data) { - return !predicate.test(data); + void appendArgument(final StringBuilder sb) { + match.appendTo(sb); } } - public static final class ValueEquals extends AbstractValueDOMQueryPredicate { - public ValueEquals(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchValueEquals extends AbstractMatchValue { + MatchValueEquals(final T value) { + super(value); } @Override - public boolean testValue(final Object data) { + String op() { + return "eq"; + } + + @Override + boolean testValue(final @Nullable Object data) { return value().equals(data); } } - public static final class GreaterThan> extends AbstractComparableDOMQueryPredicate { - public GreaterThan(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchStringContains extends AbstractMatchString { + MatchStringContains(final String value) { + super(value); + } + + @Override + String op() { + return "contains"; + } + + @Override + boolean testString(final String str) { + return str.contains(value()); + } + } + + private static final class MatchStringMatches extends AbstractMatch { + private final Pattern pattern; + + MatchStringMatches(final Pattern pattern) { + this.pattern = requireNonNull(pattern); + } + + @Override + String op() { + return "matches"; + } + + @Override + void appendArgument(final StringBuilder sb) { + sb.append(pattern); + } + + @Override + boolean testValue(final @Nullable Object data) { + return data instanceof CharSequence && pattern.matcher((CharSequence) data).matches(); + } + } + + private static final class MatchStringStartsWith extends AbstractMatchString { + MatchStringStartsWith(final String value) { + super(value); + } + + @Override + String op() { + return "startsWith"; + } + + @Override + boolean testString(final String str) { + return str.startsWith(value()); + } + } + + private static final class MatchStringEndsWith extends AbstractMatchString { + MatchStringEndsWith(final String value) { + super(value); + } + + @Override + String op() { + return "endsWith"; + } + + @Override + boolean testString(final String str) { + return str.endsWith(value()); + } + } + + private static final class MatchGreaterThan> extends AbstractMatchComparable { + MatchGreaterThan(final T value) { + super(value); } @Override - boolean test(final int valueToData) { + String op() { + return "gt"; + } + + @Override + boolean testCompare(final int valueToData) { return valueToData <= 0; } } - public static final class GreaterThanOrEqual> - extends AbstractComparableDOMQueryPredicate { - public GreaterThanOrEqual(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchGreaterThanOrEqual> extends AbstractMatchComparable { + MatchGreaterThanOrEqual(final T value) { + super(value); } @Override - boolean test(final int valueToData) { + String op() { + return "gte"; + } + + @Override + boolean testCompare(final int valueToData) { return valueToData < 0; } } - public static final class LessThan> extends AbstractComparableDOMQueryPredicate { - public LessThan(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchLessThan> extends AbstractMatchComparable { + MatchLessThan(final T value) { + super(value); + } + + @Override + String op() { + return "lt"; } @Override - boolean test(final int valueToData) { + boolean testCompare(final int valueToData) { return valueToData >= 0; } } - public static final class LessThanOrEqual> extends AbstractComparableDOMQueryPredicate { - public LessThanOrEqual(final YangInstanceIdentifier relativePath, final T value) { - super(relativePath, value); + private static final class MatchLessThanOrEqual> extends AbstractMatchComparable { + MatchLessThanOrEqual(final T value) { + super(value); } @Override - boolean test(final int valueToData) { + String op() { + return "lte"; + } + + @Override + boolean testCompare(final int valueToData) { return valueToData > 0; } } - public static final class StartsWith extends AbstractStringDOMQueryPredicate { - public StartsWith(final YangInstanceIdentifier relativePath, final String str) { - super(relativePath, str); + private abstract static class CompositeMatch extends Match { + private final ImmutableList components; + + CompositeMatch(final ImmutableList components) { + this.components = requireNonNull(components); + } + + final ImmutableList components() { + return components; + } + + final ImmutableList newComponents(final Match nextComponent) { + return ImmutableList.builderWithExpectedSize(components.size() + 1) + .addAll(components) + .add(nextComponent) + .build(); } @Override - boolean test(final String str) { - return str.startsWith(value()); + final void appendArgument(final StringBuilder sb) { + final Iterator it = components.iterator(); + sb.append(it.next()); + while (it.hasNext()) { + sb.append(", ").append(it.next()); + } } } - public static final class EndsWith extends AbstractStringDOMQueryPredicate { - public EndsWith(final YangInstanceIdentifier relativePath, final String str) { - super(relativePath, str); + private abstract static class AbstractMatch extends Match { + AbstractMatch() { + // Hidden on purpose } @Override - boolean test(final String str) { - return str.endsWith(value()); + public final boolean test(final @Nullable NormalizedNode data) { + return data instanceof LeafNode ? testValue(((LeafNode) data).getValue()) : testValue(null); } + + abstract boolean testValue(@Nullable Object data); } - public static final class Contains extends AbstractStringDOMQueryPredicate { - public Contains(final YangInstanceIdentifier relativePath, final String str) { - super(relativePath, str); + private abstract static class AbstractMatchComparable> extends AbstractMatchValue { + AbstractMatchComparable(final T value) { + super(value); } @Override - boolean test(final String str) { - return str.contains(value()); + @SuppressWarnings("unchecked") + final boolean testValue(final @Nullable Object data) { + return data != null && testCompare(value().compareTo((T) data)); } - } - public static final class MatchesPattern extends AbstractLeafDOMQueryPredicate { - private final Pattern pattern; + abstract boolean testCompare(int valueToData); + } - public MatchesPattern(final YangInstanceIdentifier relativePath, final Pattern pattern) { - super(relativePath); - this.pattern = requireNonNull(pattern); + private abstract static class AbstractMatchString extends AbstractMatchValue { + AbstractMatchString(final String value) { + super(value); } @Override - public boolean testValue(final Object data) { - return data instanceof CharSequence && pattern.matcher((CharSequence) data).matches(); + final boolean testValue(final @Nullable Object data) { + return data instanceof String && testString((String) data); + } + + abstract boolean testString(String str); + } + + private abstract static class AbstractMatchValue extends AbstractMatch { + private final @NonNull T value; + + AbstractMatchValue(final T value) { + this.value = requireNonNull(value); + } + + final @NonNull T value() { + return value; } @Override - ToStringHelper addToStringAttributes(final ToStringHelper helper) { - return helper.add("pattern", pattern); + final void appendArgument(final StringBuilder sb) { + sb.append(value); } } - private final @NonNull YangInstanceIdentifier relativePath; + private final YangInstanceIdentifier relativePath; + private final Match match; - DOMQueryPredicate(final YangInstanceIdentifier relativePath) { + private DOMQueryPredicate(final YangInstanceIdentifier relativePath, final Match match) { this.relativePath = requireNonNull(relativePath); + this.match = requireNonNull(match); } - public final @NonNull YangInstanceIdentifier getPath() { - return relativePath; + public static DOMQueryPredicate of(final YangInstanceIdentifier relativePath, final Match match) { + return new DOMQueryPredicate(relativePath, match); } - @Override - public @NonNull DOMQueryPredicate negate() { - return new Not(this); + public YangInstanceIdentifier relativePath() { + return relativePath; } - @Override - public abstract boolean test(@Nullable NormalizedNode data); + public Match match() { + return match; + } @Override public String toString() { - return addToStringAttributes(MoreObjects.toStringHelper(this).add("path", relativePath)).toString(); - } - - ToStringHelper addToStringAttributes(final ToStringHelper helper) { - return helper; + return MoreObjects.toStringHelper(this).add("path", relativePath).add("match", match).toString(); } } diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryEvaluator.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryEvaluator.java index 5dceb89b79..414f615d5a 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryEvaluator.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryEvaluator.java @@ -60,7 +60,7 @@ public final class DOMQueryEvaluator { } private static DOMQueryResult evalSingle(final DOMQuery query, final NormalizedNode data) { - return DOMQueryMatcher.matches(data, query.getPredicates()) ? DOMQueryResult.of() + return DOMQueryMatcher.matchesAll(data, query.getPredicates()) ? DOMQueryResult.of() : DOMQueryResult.of(new SimpleImmutableEntry<>(query.getRoot(), data)); } } diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryIterator.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryIterator.java index e911456d43..ff11e82984 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryIterator.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryIterator.java @@ -329,6 +329,6 @@ final class DOMQueryIterator extends AbstractIterator data) { - return DOMQueryMatcher.matches(data, predicates); + return DOMQueryMatcher.matchesAll(data, predicates); } } diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java index 7c9797fd16..e5904ecac3 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java @@ -12,7 +12,7 @@ import java.util.Deque; import java.util.List; import java.util.Optional; import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate; -import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Not; +import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.Match; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -29,7 +29,7 @@ final class DOMQueryMatcher { // Utility class } - static boolean matches(final NormalizedNode data, final List predicates) { + static boolean matchesAll(final NormalizedNode data, final List predicates) { // TODO: it would be nice if predicates were somehow structured -- can we perhaps sort them by their // InstanceIdentifier? If the predicates are sharing a common subpath. Hence if we can guarantee // predicates are in a certain order, we would not end up in subsequent re-lookups of the same node. @@ -38,13 +38,9 @@ final class DOMQueryMatcher { // So now, dealing with implementations: YangInstanceIdentifier.getLastPathArgument() is always cheap. // If its parent is YangInstanceIdentifier.ROOT (i.e. isEmpty() == true), we are dealing with a last-step // lookup -- in which case we forgo iteration: - final YangInstanceIdentifier path = pred.getPath(); + final YangInstanceIdentifier path = pred.relativePath(); if (path.coerceParent().isEmpty()) { - if (pred instanceof Not) { - if (matchesChild(((Not) pred).predicate(), data, path.getLastPathArgument())) { - return false; - } - } else if (!matchesChild(pred, data, path.getLastPathArgument())) { + if (!matchesChild(pred.match(), data, path.getLastPathArgument())) { return false; } continue; @@ -57,11 +53,7 @@ final class DOMQueryMatcher { pathArgs.addAll(path.getPathArguments()); // The stage is set, we now have to deal with potential negation. - if (pred instanceof Not) { - if (matchesAny(((Not) pred).predicate(), data, pathArgs)) { - return false; - } - } else if (!matchesAny(pred, data, pathArgs)) { + if (!matchesAny(pred.match(), data, pathArgs)) { return false; } @@ -70,19 +62,19 @@ final class DOMQueryMatcher { return true; } - private static boolean matchesAny(final DOMQueryPredicate pred, final NormalizedNode data, + private static boolean matchesAny(final Match match, final NormalizedNode data, final Deque pathArgs) { // Guaranteed to have at least one item final PathArgument pathArg = pathArgs.pop(); // Ultimate item -- reuse lookup & match if (pathArgs.isEmpty()) { pathArgs.push(pathArg); - return matchesChild(pred, data, pathArg); + return matchesChild(match, data, pathArg); } final Optional> direct = NormalizedNodes.getDirectChild(data, pathArg); if (direct.isPresent()) { - final boolean ret = matchesAny(pred, direct.orElseThrow(), pathArgs); + final boolean ret = matchesAny(match, direct.orElseThrow(), pathArgs); pathArgs.push(pathArg); return ret; } @@ -90,7 +82,7 @@ final class DOMQueryMatcher { // We may be dealing with a wildcard here. NodeIdentifier is a final class, hence this is as fast as it gets. if (pathArg instanceof NodeIdentifier && data instanceof MapNode) { for (MapEntryNode child : ((MapNode) data).getValue()) { - if (matchesAny(pred, child, pathArgs)) { + if (matchesAny(match, child, pathArgs)) { pathArgs.push(pathArg); return true; } @@ -101,23 +93,23 @@ final class DOMQueryMatcher { return false; } - private static boolean matchesChild(final DOMQueryPredicate pred, final NormalizedNode data, + private static boolean matchesChild(final Match match, final NormalizedNode data, final PathArgument pathArg) { // Try the direct approach... final Optional> direct = NormalizedNodes.getDirectChild(data, pathArg); if (direct.isPresent()) { - return pred.test(direct.orElseThrow()); + return match.test(direct.orElseThrow()); } // We may be dealing with a wildcard here. NodeIdentifier is a final class, hence this is as fast as it gets. if (pathArg instanceof NodeIdentifier && data instanceof MapNode) { for (MapEntryNode child : ((MapNode) data).getValue()) { - if (pred.test(child)) { + if (match.test(child)) { return true; } } } - return false; + return match.test(null); } } -- 2.36.6