Migrate getDataChildByName() users
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / DataSchemaContextNode.java
index 050255e921b5ddac6595328afcde71c507b09a36..8070db3c3170e30fa8c917e5408d2be5fb65fabc 100644 (file)
@@ -7,55 +7,46 @@
  */
 package org.opendaylight.yangtools.yang.data.util;
 
-
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
-import java.util.Collections;
-import java.util.HashSet;
+import com.google.common.collect.Iterables;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
-import javax.annotation.Nullable;
-import org.opendaylight.yangtools.concepts.Identifiable;
+import java.util.stream.Collectors;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 
 /**
- * Schema derived data providing necessary information for mapping
- * between {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode}
- * and serialization format defined in RFC6020, since the mapping
- * is not one-to-one.
+ * Schema derived data providing necessary information for mapping between
+ * {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode} and serialization format defined in RFC6020,
+ * since the mapping is not one-to-one.
  *
  * @param <T> Path Argument type
- *
  */
-public abstract class DataSchemaContextNode<T extends PathArgument> implements Identifiable<T> {
-
-    private final T identifier;
+public abstract class DataSchemaContextNode<T extends PathArgument> extends AbstractIdentifiable<T> {
     private final DataSchemaNode dataSchemaNode;
 
-    @Override
-    public T getIdentifier() {
-        return identifier;
-    };
-
     protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
-        super();
-        this.identifier = identifier;
+        super(identifier);
         if (schema instanceof DataSchemaNode) {
             this.dataSchemaNode = (DataSchemaNode) schema;
         } else {
@@ -71,114 +62,119 @@ public abstract class DataSchemaContextNode<T extends PathArgument> implements I
         return false;
     }
 
+    public abstract boolean isLeaf();
+
     protected Set<QName> getQNameIdentifiers() {
-        return Collections.singleton(identifier.getNodeType());
+        return ImmutableSet.of(getIdentifier().getNodeType());
     }
 
-    public abstract @Nullable DataSchemaContextNode<?> getChild(final PathArgument child);
+    /**
+     * Find a child node identifier by its {@link PathArgument}.
+     *
+     * @param child Child path argument
+     * @return A child node, or null if not found
+     */
+    public abstract @Nullable DataSchemaContextNode<?> getChild(PathArgument child);
 
     public abstract @Nullable DataSchemaContextNode<?> getChild(QName child);
 
-    public abstract boolean isLeaf();
-
-
     public @Nullable DataSchemaNode getDataSchemaNode() {
         return dataSchemaNode;
     }
 
-    static final DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
-        DataSchemaNode potential = parent.getDataChildByName(child);
-        if (potential == null) {
-            Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
-                    parent.getChildNodes()).filter(ChoiceNode.class);
-            potential = findChoice(choices, child);
+    /**
+     * Find a child node as identified by a {@link YangInstanceIdentifier} relative to this node.
+     *
+     * @param path Path towards the child node
+     * @return Child node if present, or empty when corresponding child is not found.
+     * @throws NullPointerException if {@code path} is null
+     */
+    public final @NonNull Optional<@NonNull DataSchemaContextNode<?>> findChild(
+            final @NonNull YangInstanceIdentifier path) {
+        DataSchemaContextNode<?> currentOp = this;
+        for (PathArgument arg : path.getPathArguments()) {
+            currentOp = currentOp.getChild(arg);
+            if (currentOp == null) {
+                return Optional.empty();
+            }
         }
-        return potential;
+        return Optional.of(currentOp);
+    }
+
+    static DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
+        final DataSchemaNode potential = parent.dataChildByName(child);
+        return potential == null ? findChoice(Iterables.filter(parent.getChildNodes(), ChoiceSchemaNode.class), child)
+                : potential;
     }
 
     static DataSchemaContextNode<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
-        DataSchemaNode result = findChildSchemaNode(schema, child);
+        final DataSchemaNode result = findChildSchemaNode(schema, child);
         // We try to look up if this node was added by augmentation
-        if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+        if (result != null && schema instanceof DataSchemaNode && result.isAugmenting()) {
             return fromAugmentation(schema, (AugmentationTarget) schema, result);
         }
         return fromDataSchemaNode(result);
     }
 
-    private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
-            final Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices, final QName child) {
-        org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
-        choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
-            for (ChoiceCaseNode caze : choice.getCases()) {
+    // FIXME: this looks like it should be a Predicate on a stream with findFirst()
+    private static ChoiceSchemaNode findChoice(final Iterable<ChoiceSchemaNode> choices, final QName child) {
+        for (ChoiceSchemaNode choice : choices) {
+            // FIXME: this looks weird: what are we looking for again?
+            for (CaseSchemaNode caze : choice.getCases()) {
                 if (findChildSchemaNode(caze, child) != null) {
-                    foundChoice = choice;
-                    break choiceLoop;
+                    return choice;
                 }
             }
         }
-        return foundChoice;
-    }
-
-    public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
-        ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
-        for (DataSchemaNode child : augmentation.getChildNodes()) {
-            potentialChildren.add(child.getQName());
-        }
-        return new AugmentationIdentifier(potentialChildren.build());
+        return null;
     }
 
-    static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation,
-            final DataNodeContainer schema) {
-        Set<DataSchemaNode> children = new HashSet<>();
-        for (DataSchemaNode augNode : augmentation.getChildNodes()) {
-            children.add(schema.getDataChildByName(augNode.getQName()));
-        }
-        return new EffectiveAugmentationSchema(augmentation, children);
+    /**
+     * Create AugmentationIdentifier from an AugmentationSchemaNode.
+     *
+     * @param schema Augmentation schema
+     * @return AugmentationIdentifier for the schema
+     * @throws NullPointerException if {@code schema} is null
+     */
+    public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchemaNode schema) {
+        return new AugmentationIdentifier(schema.getChildNodes().stream().map(DataSchemaNode::getQName)
+            .collect(Collectors.toSet()));
     }
 
     /**
      * Returns a DataContextNodeOperation for provided child node
      *
+     * <p>
      * If supplied child is added by Augmentation this operation returns a
      * DataContextNodeOperation for augmentation, otherwise returns a
      * DataContextNodeOperation for child as call for
      * {@link #fromDataSchemaNode(DataSchemaNode)}.
-     *
-     *
-     * @param parent
-     * @param parentAug
-     * @param child
-     * @return
      */
     static @Nullable DataSchemaContextNode<?> fromAugmentation(final DataNodeContainer parent,
             final AugmentationTarget parentAug, final DataSchemaNode child) {
-        AugmentationSchema augmentation = null;
-        for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
-            DataSchemaNode potential = aug.getDataChildByName(child.getQName());
-            if (potential != null) {
-                augmentation = aug;
-                break;
+        for (AugmentationSchemaNode aug : parentAug.getAvailableAugmentations()) {
+            if (aug.findDataChildByName(child.getQName()).isPresent()) {
+                return new AugmentationContextNode(aug, parent);
             }
         }
-        if (augmentation != null) {
-            return new AugmentationContextNode(augmentation, parent);
-        }
         return fromDataSchemaNode(child);
     }
 
     public static @Nullable DataSchemaContextNode<?> fromDataSchemaNode(final DataSchemaNode potential) {
-        if (potential instanceof ContainerSchemaNode) {
-            return new ContainerContextNode((ContainerSchemaNode) potential);
+        if (potential instanceof ContainerLike) {
+            return new ContainerContextNode((ContainerLike) potential);
         } else if (potential instanceof ListSchemaNode) {
             return fromListSchemaNode((ListSchemaNode) potential);
         } else if (potential instanceof LeafSchemaNode) {
             return new LeafContextNode((LeafSchemaNode) potential);
-        } else if (potential instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
-            return new ChoiceNodeContextNode((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
+        } else if (potential instanceof ChoiceSchemaNode) {
+            return new ChoiceNodeContextNode((ChoiceSchemaNode) potential);
         } else if (potential instanceof LeafListSchemaNode) {
             return fromLeafListSchemaNode((LeafListSchemaNode) potential);
-        } else if (potential instanceof AnyXmlSchemaNode) {
-            return new AnyXmlContextNode((AnyXmlSchemaNode) potential);
+        } else if (potential instanceof AnydataSchemaNode) {
+            return new AnydataContextNode((AnydataSchemaNode) potential);
+        } else if (potential instanceof AnyxmlSchemaNode) {
+            return new AnyXmlContextNode((AnyxmlSchemaNode) potential);
         }
         return null;
     }
@@ -201,7 +197,7 @@ public abstract class DataSchemaContextNode<T extends PathArgument> implements I
         return new UnorderedLeafListMixinContextNode(potential);
     }
 
-    public static DataSchemaContextNode<?> from(final SchemaContext ctx) {
+    public static DataSchemaContextNode<?> from(final EffectiveModelContext ctx) {
         return new ContainerContextNode(ctx);
     }
 }