Add DOMQueryResult streaming interfaces 63/93363/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 25 Oct 2020 23:40:40 +0000 (00:40 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 26 Oct 2020 00:01:29 +0000 (01:01 +0100)
Current definition is really an implementation-specific. The API
exposed from DOMQueryResult is eager, not allowing for eager
termination of searching.

Fix this by turning DOMQueryResult into an interface and add
an eager implementation to match current behavior.

Also update DefaultQueryResult to take advantage of lazy
transformations.

JIRA: MDSAL-605
Change-Id: I8375954e09ce6139aad0f83e883ed75771faceab
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultQuery.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultQueryResult.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultQueryResultSpliterator.java [new file with mode: 0644]
dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/query/DOMQueryResult.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/EagerDOMQueryResult.java [new file with mode: 0644]

index d0f73440e5845d737565a18b31933a8fcd9de3ab..0539fd0c44908fcda4045467ae812800fc8d0327 100644 (file)
@@ -37,7 +37,7 @@ public final class DefaultQuery<T extends DataObject> implements QueryExpression
     }
 
     public QueryResult<T> toQueryResult(final DOMQueryResult domResult) {
-        return new DefaultQueryResult<>(codec, domResult.items());
+        return new DefaultQueryResult<>(codec, domResult);
     }
 
     @Override
index 516a83e5960e2d94db217056840541a086b90e2c..8281101cfa6ab729df17dbff2da2de2e8728b57e 100644 (file)
@@ -10,30 +10,27 @@ package org.opendaylight.mdsal.binding.dom.adapter.query;
 import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Function;
 import com.google.common.base.VerifyException;
-import com.google.common.collect.Lists;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
-import java.util.List;
 import java.util.Map.Entry;
 import java.util.Spliterator;
+import java.util.function.Function;
 import java.util.stream.Stream;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
-import org.gaul.modernizer_maven_annotations.SuppressModernizer;
 import org.opendaylight.mdsal.binding.api.query.QueryResult;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
+import org.opendaylight.mdsal.dom.api.query.DOMQueryResult;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
 @NonNullByDefault
-@SuppressModernizer
 final class DefaultQueryResult<T extends DataObject>
         implements QueryResult<T>, Function<Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>, QueryResult.Item<T>> {
     private static final VarHandle ITEM_CODEC;
@@ -47,22 +44,21 @@ final class DefaultQueryResult<T extends DataObject>
         }
     }
 
-    private final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> domResult;
+    private final DOMQueryResult domResult;
     private final BindingCodecTree codec;
 
     @SuppressWarnings("unused")
     @SuppressFBWarnings(value = "NP_STORE_INTO_NONNULL_FIELD", justification = "Ungrokked type annotation")
     private volatile @Nullable BindingDataObjectCodecTreeNode<T> itemCodec = null;
 
-    DefaultQueryResult(final BindingCodecTree codec,
-            final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> domResult) {
+    DefaultQueryResult(final BindingCodecTree codec, final DOMQueryResult domResult) {
         this.codec = requireNonNull(codec);
         this.domResult = requireNonNull(domResult);
     }
 
     @Override
     public Spliterator<? extends Item<T>> spliterator() {
-        return Lists.transform(domResult, this).spliterator();
+        return new DefaultQueryResultSpliterator<>(this, domResult.spliterator());
     }
 
     @Override
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultQueryResultSpliterator.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultQueryResultSpliterator.java
new file mode 100644 (file)
index 0000000..b239ec2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.binding.dom.adapter.query;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Map.Entry;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.api.query.QueryResult;
+import org.opendaylight.mdsal.binding.api.query.QueryResult.Item;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+@NonNullByDefault
+final class DefaultQueryResultSpliterator<T extends DataObject> implements Spliterator<QueryResult.Item<T>> {
+    private final Spliterator<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> domSpliterator;
+    private final DefaultQueryResult<T> result;
+
+    DefaultQueryResultSpliterator(final DefaultQueryResult<T> result,
+            final Spliterator<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> domSpliterator) {
+        this.result = requireNonNull(result);
+        this.domSpliterator = requireNonNull(domSpliterator);
+    }
+
+    @Override
+    public boolean tryAdvance(final @Nullable Consumer<? super Item<T>> action) {
+        return domSpliterator.tryAdvance(dom -> action.accept(new DefaultQueryResultItem<>(result, dom)));
+    }
+
+    @Override
+    public @Nullable Spliterator<Item<T>> trySplit() {
+        final Spliterator<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> split =
+            domSpliterator.trySplit();
+        return split == null ? null : new DefaultQueryResultSpliterator<>(result, split);
+    }
+
+    @Override
+    public long estimateSize() {
+        return domSpliterator.estimateSize();
+    }
+
+    @Override
+    public long getExactSizeIfKnown() {
+        return domSpliterator.getExactSizeIfKnown();
+    }
+
+    @Override
+    public int characteristics() {
+        return domSpliterator.characteristics();
+    }
+}
index 71386624cc9488214e751adfc976f9a2607e94b9..14025c8ad2125ffbe4ce9ae9fd8a3b746c8861c2 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.mdsal.dom.api.query;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.Spliterator;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -21,24 +23,15 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
  */
 @Beta
 @NonNullByDefault
-public final class DOMQueryResult implements Immutable {
-    private static final DOMQueryResult EMPTY_INSTANCE = new DOMQueryResult(ImmutableList.of());
+public interface DOMQueryResult extends Immutable {
 
-    private final ImmutableList<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items;
+    Spliterator<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> spliterator();
 
-    private DOMQueryResult(final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items) {
-        this.items = ImmutableList.copyOf(items);
-    }
-
-    public static DOMQueryResult of() {
-        return EMPTY_INSTANCE;
-    }
+    Stream<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> stream();
 
-    public static DOMQueryResult of(final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items) {
-        return items.isEmpty() ? of() : new DOMQueryResult(items);
-    }
+    Stream<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> parallelStream();
 
-    public List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items() {
-        return items;
+    default List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items() {
+        return stream().collect(Collectors.toUnmodifiableList());
     }
 }
index 12df752e9d7aad26d471e29d7dc847c60c17b3cf..671b8eadd92cc5d95dbf52022bc75337ba9bd9fd 100644 (file)
@@ -64,7 +64,7 @@ public final class DOMQueryEvaluator {
         for (PathArgument arg : query.getRoot().getPathArguments()) {
             final Optional<NormalizedNode<?, ?>> next = NormalizedNodes.findNode(root, arg);
             if (next.isEmpty()) {
-                return DOMQueryResult.of();
+                return EagerDOMQueryResult.of();
             }
             evalRoot = next.orElseThrow();
         }
@@ -75,7 +75,7 @@ public final class DOMQueryEvaluator {
             final DOMQuery query) {
         final List<Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> result = new ArrayList<>();
         evalPath(result, new ArrayDeque<>(query.getRoot().getPathArguments()), remaining, data, query);
-        return DOMQueryResult.of(result);
+        return EagerDOMQueryResult.of(result);
     }
 
     private static void evalPath(final List<Entry<YangInstanceIdentifier, NormalizedNode<?,?>>> result,
@@ -110,8 +110,8 @@ public final class DOMQueryEvaluator {
     }
 
     private static DOMQueryResult evalSingle(final NormalizedNode<?, ?> data, final DOMQuery query) {
-        return matches(data, query) ? DOMQueryResult.of()
-                : DOMQueryResult.of(List.of(new SimpleImmutableEntry<>(query.getRoot(), data)));
+        return matches(data, query) ? EagerDOMQueryResult.of()
+                : EagerDOMQueryResult.of(new SimpleImmutableEntry<>(query.getRoot(), data));
     }
 
     private static boolean matches(final NormalizedNode<?, ?> data, final DOMQuery query) {
diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/EagerDOMQueryResult.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/query/EagerDOMQueryResult.java
new file mode 100644 (file)
index 0000000..33d6a47
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Spliterator;
+import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.mdsal.dom.api.query.DOMQueryResult;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+@Beta
+@NonNullByDefault
+public final class EagerDOMQueryResult implements DOMQueryResult {
+    private static final EagerDOMQueryResult EMPTY_INSTANCE = new EagerDOMQueryResult(ImmutableList.of());
+
+    private final ImmutableList<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items;
+
+    private EagerDOMQueryResult(final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items) {
+        this.items = ImmutableList.copyOf(items);
+    }
+
+    public static EagerDOMQueryResult of() {
+        return EMPTY_INSTANCE;
+    }
+
+    public static EagerDOMQueryResult of(final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> item) {
+        return new EagerDOMQueryResult(ImmutableList.of(item));
+    }
+
+    public static EagerDOMQueryResult of(
+            final List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items) {
+        return items.isEmpty() ? of() : new EagerDOMQueryResult(items);
+    }
+
+    @Override
+    public Spliterator<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> spliterator() {
+        return items.spliterator();
+    }
+
+    @Override
+    public Stream<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> stream() {
+        return items.stream();
+    }
+
+    @Override
+    public Stream<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> parallelStream() {
+        return items.parallelStream();
+    }
+
+    @Override
+    public List<? extends Entry<YangInstanceIdentifier, NormalizedNode<?, ?>>> items() {
+        return items;
+    }
+}