X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-spi%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fspi%2Fquery%2FDOMQueryEvaluator.java;h=671b8eadd92cc5d95dbf52022bc75337ba9bd9fd;hb=b620c86025390e3f86eaade9f9c0f102ce6313fa;hp=09b2a8a032ab80ae98c2c99d466e274f70140b47;hpb=720a57a5099da2bb3595e66fe49074776776880b;p=mdsal.git 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 09b2a8a032..671b8eadd9 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 @@ -9,16 +9,17 @@ package org.opendaylight.mdsal.dom.spi.query; import static com.google.common.base.Preconditions.checkArgument; -import com.google.common.collect.ImmutableList; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; import java.util.Map.Entry; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.mdsal.dom.api.query.DOMQuery; import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; 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; @@ -33,36 +34,57 @@ public final class DOMQueryEvaluator { } - public static List>> evaluate(final DOMQuery query, - final NormalizedNode root) { + /** + * Evaluate {@link DOMQuery} on its data element. The element is expected to correspond to + * {@link DOMQuery#getRoot()}. + * + * @param query Query to execute + * @param queryRoot Query root object + * @return Result of evaluation + * @throws NullPointerException if any argument is null + */ + public static DOMQueryResult evaluateOn(final DOMQuery query, final NormalizedNode queryRoot) { final YangInstanceIdentifier path = query.getSelect(); - return path.isEmpty() ? evalSingle(root, query) - : evalPath(new ArrayDeque<>(path.getPathArguments()), root, query); + return path.isEmpty() ? evalSingle(queryRoot, query) + : evalPath(new ArrayDeque<>(path.getPathArguments()), queryRoot, query); } - private static List>> evalPath( - final ArrayDeque remaining, final NormalizedNode data, final DOMQuery query) { - NormalizedNode evalRoot = data; + /** + * Evaluate {@link DOMQuery} on a conceptual root. The element is expected to correspond to the conceptual data tree + * root. This method will first find the {@link DOMQuery#getRoot()} and then defer to + * {@link #evaluateOn(DOMQuery, NormalizedNode)}. + * + * @param query Query to execute + * @param root Conceptual root object + * @return Result of evaluation + * @throws NullPointerException if any argument is null + */ + public static DOMQueryResult evaluateOnRoot(final DOMQuery query, final NormalizedNode root) { + NormalizedNode evalRoot = root; for (PathArgument arg : query.getRoot().getPathArguments()) { - final Optional> next = NormalizedNodes.findNode(data, arg); + final Optional> next = NormalizedNodes.findNode(root, arg); if (next.isEmpty()) { - return ImmutableList.of(); + return EagerDOMQueryResult.of(); } evalRoot = next.orElseThrow(); } + return evaluateOn(query, evalRoot); + } + private static DOMQueryResult evalPath(final ArrayDeque remaining, final NormalizedNode data, + final DOMQuery query) { final List>> result = new ArrayList<>(); - evalPath(result, query.getRoot(), remaining, evalRoot, query); - return result; + evalPath(result, new ArrayDeque<>(query.getRoot().getPathArguments()), remaining, data, query); + return EagerDOMQueryResult.of(result); } private static void evalPath(final List>> result, - final YangInstanceIdentifier path, final ArrayDeque remaining, + final Deque path, final ArrayDeque remaining, final NormalizedNode data, final DOMQuery query) { final PathArgument next = remaining.poll(); if (next == null) { if (matches(data, query)) { - result.add(new SimpleImmutableEntry<>(path, data)); + result.add(new SimpleImmutableEntry<>(YangInstanceIdentifier.create(path), data)); } return; } @@ -70,24 +92,41 @@ public final class DOMQueryEvaluator { if (data instanceof MapNode && next instanceof NodeIdentifier) { checkArgument(data.getIdentifier().equals(next), "Unexpected step %s", next); for (MapEntryNode child : ((MapNode) data).getValue()) { - evalPath(result, path.node(child.getIdentifier()), remaining, child, query); + evalChild(result, path, remaining, query, child); } } else { NormalizedNodes.getDirectChild(data, next).ifPresent( - child -> evalPath(result, path.node(next), remaining, child, query)); + child -> evalChild(result, path, remaining, query, child)); } remaining.push(next); } - private static List>> evalSingle( - final NormalizedNode data, final DOMQuery query) { - return matches(data, query) ? ImmutableList.of() - : ImmutableList.of(new SimpleImmutableEntry<>(query.getRoot(), data)); + private static void evalChild(final List>> result, + final Deque path, final ArrayDeque remaining, final DOMQuery query, + final NormalizedNode child) { + path.addLast(child.getIdentifier()); + evalPath(result, path, remaining, child, query); + path.removeLast(); + } + + private static DOMQueryResult evalSingle(final NormalizedNode data, final DOMQuery query) { + return matches(data, query) ? EagerDOMQueryResult.of() + : EagerDOMQueryResult.of(new SimpleImmutableEntry<>(query.getRoot(), data)); } private static boolean matches(final NormalizedNode data, final DOMQuery query) { for (DOMQueryPredicate pred : query.getPredicates()) { - if (!pred.test(NormalizedNodes.findNode(data, pred.getPath()).orElse(null))) { + // Okay, now we need to deal with predicates, but do it in a smart fashion, so we do not end up iterating + // all over the place. Typically we will be matching just a leaf. + final YangInstanceIdentifier path = pred.getPath(); + final Optional> node; + if (path.coerceParent().isEmpty()) { + node = NormalizedNodes.getDirectChild(data, path.getLastPathArgument()); + } else { + node = NormalizedNodes.findNode(data, path); + } + + if (!pred.test(node.orElse(null))) { return false; } }