Revert "Add support for keyed entries" 48/93448/1
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 28 Oct 2020 11:10:15 +0000 (12:10 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 28 Oct 2020 11:11:10 +0000 (12:11 +0100)
This reverts commit afc860cd2e669832d2df5bf0d8b59faa0ff52834, as it
was accidentally pushed without review.

Change-Id: If692ea0f130e4d08846efb5ba17d62f88fc7477f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/AbstractValueMatchBuilder.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/query/QueryBuilderTest.java
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryPredicate.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryEvaluator.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java [deleted file]
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/LazyDOMQueryResultIterator.java

index 47a32b96bdf0ffba13a639fa6dae1fb0131b955c..080a5c826fded00fdf43791a97f516ba32eeb2be 100644 (file)
@@ -15,6 +15,7 @@ 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.NotExists;
 import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate.ValueEquals;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -40,7 +41,7 @@ abstract class AbstractValueMatchBuilder<T extends DataObject, V> implements Val
 
     @Override
     public final ValueMatch<T> isNull() {
-        return withPredicate(new Exists(relativePath()).negate());
+        return withPredicate(new NotExists(relativePath()));
     }
 
     @Override
index 983929fcfb6f3fffb39eb6765413bfc68c4a879b..d9b8d78623a67ac301712db2eeeeeed45b070762 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.mdsal.binding.api.query.QueryExpression;
 import org.opendaylight.mdsal.binding.api.query.QueryFactory;
 import org.opendaylight.mdsal.binding.api.query.QueryResult;
 import org.opendaylight.mdsal.binding.api.query.QueryResult.Item;
+import org.opendaylight.mdsal.binding.api.query.QueryStructureException;
 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
 import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
@@ -30,7 +31,6 @@ import org.opendaylight.yang.gen.v1.mdsal.query.norev.Foo;
 import org.opendaylight.yang.gen.v1.mdsal.query.norev.FooBuilder;
 import org.opendaylight.yang.gen.v1.mdsal.query.norev.first.grp.System;
 import org.opendaylight.yang.gen.v1.mdsal.query.norev.first.grp.SystemBuilder;
-import org.opendaylight.yang.gen.v1.mdsal.query.norev.first.grp.SystemKey;
 import org.opendaylight.yang.gen.v1.mdsal.query.norev.second.grp.Alarms;
 import org.opendaylight.yang.gen.v1.mdsal.query.norev.second.grp.AlarmsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
@@ -102,7 +102,7 @@ public class QueryBuilderTest {
     }
 
     @Test
-    public void bar() {
+    public void bar() throws QueryStructureException {
         final Stopwatch sw = Stopwatch.createStarted();
         final QueryExpression<TopLevelList> query = factory.querySubtree(InstanceIdentifier.create(Top.class))
                 .extractChild(TopLevelList.class)
@@ -117,7 +117,7 @@ public class QueryBuilderTest {
     }
 
     @Test
-    public void testFindCriticalAlarms() {
+    public void testFindCriticalAlarms() throws QueryStructureException {
         final Stopwatch sw = Stopwatch.createStarted();
         final QueryExpression<Alarms> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
             .extractChild(System.class)
@@ -132,7 +132,7 @@ public class QueryBuilderTest {
     }
 
     @Test
-    public void testFindNonCriticalAlarms() {
+    public void testFindNonCriticalAlarms() throws QueryStructureException {
         final Stopwatch sw = Stopwatch.createStarted();
         final QueryExpression<Alarms> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
             .extractChild(System.class)
@@ -147,7 +147,7 @@ public class QueryBuilderTest {
     }
 
     @Test
-    public void testFindZeroAlarms() {
+    public void testFindZeroAlarms() throws QueryStructureException {
         final Stopwatch sw = Stopwatch.createStarted();
         final QueryExpression<Alarms> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
             .extractChild(System.class)
@@ -161,37 +161,6 @@ public class QueryBuilderTest {
         assertEquals(2, items.size());
     }
 
-    @Test
-    public void testFindSystemFirstAlarmOne() {
-        final Stopwatch sw = Stopwatch.createStarted();
-        final QueryExpression<Alarms> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
-            .extractChild(System.class, new SystemKey("first"))
-            .extractChild(Alarms.class)
-                .matching()
-                    .leaf(Alarms::getId).valueEquals(Uint64.ZERO)
-                .build();
-        LOG.info("Query built in {}", sw);
-
-        final List<? extends Item<@NonNull Alarms>> items = execute(query).getItems();
-        assertEquals(1, items.size());
-    }
-
-    @Test
-    public void testFindSystemFirstWithAlarmOne() {
-        final Stopwatch sw = Stopwatch.createStarted();
-        final QueryExpression<System> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
-            .extractChild(System.class, new SystemKey("first"))
-                .matching()
-                    .childObject(Alarms.class)
-                        .leaf(Alarms::getId).valueEquals(Uint64.ZERO)
-                .build();
-        LOG.info("Query built in {}", sw);
-
-        final List<? extends Item<@NonNull System>> items = execute(query).getItems();
-        assertEquals(1, items.size());
-    }
-
-
     private <T extends @NonNull DataObject> QueryResult<T> execute(final QueryExpression<T> query) {
         final Stopwatch sw = Stopwatch.createStarted();
         final QueryResult<T> result = executor.executeQuery(query);
index 80db6f34420efd8bced760979e9a1007a30e057e..7a36bd7b206a3391219882c12e2a4e45106400c9 100644 (file)
@@ -93,26 +93,14 @@ public abstract class DOMQueryPredicate implements Immutable, Predicate<Normaliz
         }
     }
 
-    public static final class Not extends DOMQueryPredicate {
-        private final DOMQueryPredicate predicate;
-
-        Not(final DOMQueryPredicate predicate) {
-            super(predicate.relativePath);
-            this.predicate = predicate;
-        }
-
-        public @NonNull DOMQueryPredicate predicate() {
-            return predicate;
-        }
-
-        @Override
-        public DOMQueryPredicate negate() {
-            return predicate;
+    public static final class NotExists extends DOMQueryPredicate {
+        public NotExists(final YangInstanceIdentifier relativePath) {
+            super(relativePath);
         }
 
         @Override
         public boolean test(final NormalizedNode<?, ?> data) {
-            return !predicate.test(data);
+            return data == null;
         }
     }
 
@@ -234,11 +222,6 @@ public abstract class DOMQueryPredicate implements Immutable, Predicate<Normaliz
         return relativePath;
     }
 
-    @Override
-    public @NonNull DOMQueryPredicate negate() {
-        return new Not(this);
-    }
-
     @Override
     public abstract boolean test(@Nullable NormalizedNode<?, ?> data);
 
index 5dceb89b79cc5bada1ce918031fdc75e2eabf5ac..e5483eb35008719467cc0f83540151fbc654f5bd 100644 (file)
@@ -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 LazyDOMQueryResultIterator.matches(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/DOMQueryMatcher.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/DOMQueryMatcher.java
deleted file mode 100644 (file)
index 4b9bd9f..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.dom.spi.query;
-
-import java.util.ArrayDeque;
-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.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
-
-/**
- * Generalized utility for matching predicates. Split out of {@link LazyDOMQueryResultIterator} for simplicity.
- */
-final class DOMQueryMatcher {
-    private DOMQueryMatcher() {
-        // Utility class
-    }
-
-    static boolean matches(final NormalizedNode<?, ?> data, final List<? extends DOMQueryPredicate> 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.
-        Deque<PathArgument> pathArgs = null;
-        for (DOMQueryPredicate pred : predicates) {
-            // 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();
-            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())) {
-                    return false;
-                }
-                continue;
-            }
-
-            // We are leaking path arguments in a bid for object reuse: we end up reusing same object as needed
-            if (pathArgs == null) {
-                pathArgs = new ArrayDeque<>();
-            }
-            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)) {
-                return false;
-            }
-
-            pathArgs.clear();
-        }
-        return true;
-    }
-
-    private static boolean matchesAny(final DOMQueryPredicate pred, final NormalizedNode<?, ?> data,
-            final Deque<PathArgument> 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);
-        }
-
-        final Optional<NormalizedNode<?, ?>> direct = NormalizedNodes.getDirectChild(data, pathArg);
-        if (direct.isPresent()) {
-            final boolean ret = matchesAny(pred, direct.orElseThrow(), pathArgs);
-            pathArgs.push(pathArg);
-            return ret;
-        }
-
-        // 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)) {
-                    pathArgs.push(pathArg);
-                    return true;
-                }
-            }
-        }
-
-        pathArgs.push(pathArg);
-        return false;
-    }
-
-    private static boolean matchesChild(final DOMQueryPredicate pred, final NormalizedNode<?, ?> data,
-            final PathArgument pathArg) {
-        // Try the direct approach...
-        final Optional<NormalizedNode<?, ?>> direct = NormalizedNodes.getDirectChild(data, pathArg);
-        if (direct.isPresent()) {
-            return pred.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)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-}
index 265c1b882e05fa45f52912276b38d357a5765594..dd615d15dc43f6f2822b2eaaf75610a5a500ac22 100644 (file)
@@ -25,7 +25,6 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.dom.api.query.DOMQuery;
 import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
@@ -186,7 +185,9 @@ final class LazyDOMQueryResultIterator extends AbstractIterator<Entry<YangInstan
                 // This is the ultimate step in lookup, process it without churning the stack by imposing a dedicated
                 // Frame. In either case we are done with this frame, unwinding it in both cases.
                 if (matches(child)) {
-                    return unwindAndReturn(current, next, child);
+                    final YangInstanceIdentifier childPath = createIdentifier(child);
+                    unwind(current, next);
+                    return new SimpleImmutableEntry<>(childPath, child);
                 }
 
                 current = unwind(current, next);
@@ -196,47 +197,12 @@ final class LazyDOMQueryResultIterator extends AbstractIterator<Entry<YangInstan
             // Push our state back, it's just a placeholder for 'currentSelect'. Current path points at us and so does
             // the saved Frame.
             currentPath.addLast(current.data.getIdentifier());
+            frames.push(current);
 
             // Now decide what sort of entry to push. For maps we want to start an iterator already, so it gets
             // picked up as a continuation.
-            if (child instanceof MapNode) {
-                final MapNode map = (MapNode) child;
-                final PathArgument target = remainingSelect.peek();
-                if (target instanceof NodeIdentifierWithPredicates) {
-                    final Optional<MapEntryNode> optEntry = map.getChild((NodeIdentifierWithPredicates) target);
-                    if (optEntry.isPresent()) {
-                        final MapEntryNode entry = optEntry.orElseThrow();
-                        if (remainingSelect.size() != 1) {
-                            // We need to perform further selection push this frame, an empty frame for the map and
-                            // finally a frame for the map entry.
-                            remainingSelect.pop();
-                            frames.push(current);
-                            currentPath.addLast(map.getIdentifier());
-                            frames.push(new Frame(map, next));
-                            current = new Frame(entry, target);
-                            continue;
-                        }
-
-                        // We have selected entry, see it it matches. In any case rewind, potentially returning
-                        // the match
-                        if (matches(entry)) {
-                            return unwindAndReturn(current, next, entry);
-                        }
-                    }
-
-                    // We failed to find a matching entry, unwind
-                    current = unwind(current, next);
-                    continue;
-                }
-
-                // We have a wildcard, expand it
-                frames.push(current);
-                current = new MapFrame(child, next, map.getValue().iterator());
-            } else {
-                // Next step in iteration, deal with it
-                frames.push(current);
-                current = new Frame(child, next);
-            }
+            current = child instanceof MapNode ? new MapFrame(child, next, ((MapNode) child).getValue().iterator())
+                : new Frame(child, next);
         }
 
         // All done, there be entries no more.
@@ -265,14 +231,6 @@ final class LazyDOMQueryResultIterator extends AbstractIterator<Entry<YangInstan
         return new SimpleImmutableEntry<>(childPath, child);
     }
 
-    // Unwind any leftover frames and return a matching item
-    private Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> unwindAndReturn(final Frame frame,
-            final PathArgument next, final NormalizedNode<?, ?> child) {
-        final YangInstanceIdentifier childPath = createIdentifier(child);
-        unwind(frame, next);
-        return new SimpleImmutableEntry<>(childPath, child);
-    }
-
     /**
      * Unwind the stack, discarding current frame, and possibly some others. The unwind starts with pushing {@code next}
      * to {@link #remainingSelect}, hence we remember to handle it next time around. It then defers to
@@ -329,6 +287,25 @@ final class LazyDOMQueryResultIterator extends AbstractIterator<Entry<YangInstan
     }
 
     private boolean matches(final NormalizedNode<?, ?> data) {
-        return DOMQueryMatcher.matches(data, predicates);
+        return matches(data, predicates);
+    }
+
+    static boolean matches(final NormalizedNode<?, ?> data, final List<? extends DOMQueryPredicate> predicates) {
+        for (DOMQueryPredicate pred : predicates) {
+            // 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<NormalizedNode<?, ?>> 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;
+            }
+        }
+        return true;
     }
 }