Rework NormalizedNode type hierarchy
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / InstanceIdToNodes.java
index 1eca9b8417f7a2310807fa070c271f400d41069d..8590557411cde7e07f639c1199650a61837c1df6 100644 (file)
@@ -16,22 +16,25 @@ import java.util.List;
 import java.util.Optional;
 import javax.xml.transform.dom.DOMSource;
 import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.concepts.Identifiable;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractSimpleIdentifiable;
 import org.opendaylight.yangtools.yang.common.QName;
 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.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AnydataNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+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.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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.LeafListSchemaNode;
@@ -42,16 +45,9 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
  * Base strategy for converting an instance identifier into a normalized node structure.
  * Use provided static methods for generic YangInstanceIdentifier -> NormalizedNode translation in ImmutableNodes.
  */
-abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable<T> {
-    private final T identifier;
-
+abstract class InstanceIdToNodes<T extends PathArgument> extends AbstractSimpleIdentifiable<T> {
     InstanceIdToNodes(final T identifier) {
-        this.identifier = identifier;
-    }
-
-    @Override
-    public final T getIdentifier() {
-        return identifier;
+        super(identifier);
     }
 
     /**
@@ -60,7 +56,7 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
      * @param child child identifier
      * @return transformation strategy for a specific child
      */
-    abstract InstanceIdToNodes<?> getChild(PathArgument child);
+    abstract @Nullable InstanceIdToNodes<?> getChild(PathArgument child);
 
     /**
      * Convert instance identifier into a NormalizedNode structure.
@@ -70,8 +66,8 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
      * @param operation Optional modify operation to be set on the last child
      * @return NormalizedNode structure corresponding to submitted instance ID
      */
-    abstract @NonNull NormalizedNode<?, ?> create(PathArgument first, Iterator<PathArgument> others,
-            Optional<NormalizedNode<?, ?>> deepestChild);
+    abstract @NonNull NormalizedNode create(PathArgument first, Iterator<PathArgument> others,
+            Optional<NormalizedNode> deepestChild);
 
     abstract boolean isMixin();
 
@@ -99,34 +95,61 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
         }
     }
 
-    private static final class AnyXmlNormalization extends InstanceIdToNodes<NodeIdentifier> {
-        AnyXmlNormalization(final AnyXmlSchemaNode schema) {
+    private abstract static class AbstractOpaqueNormalization extends InstanceIdToNodes<NodeIdentifier> {
+        AbstractOpaqueNormalization(final DataSchemaNode schema) {
             super(NodeIdentifier.create(schema.getQName()));
         }
 
         @Override
-        InstanceIdToNodes<?> getChild(final PathArgument child) {
+        final InstanceIdToNodes<?> getChild(final PathArgument child) {
             return null;
         }
 
         @Override
-        NormalizedNode<?, ?> create(final PathArgument first, final Iterator<PathArgument> others,
-                final Optional<NormalizedNode<?, ?>> deepestChild) {
-            final NormalizedNodeBuilder<NodeIdentifier, DOMSource, AnyXmlNode> builder = Builders.anyXmlBuilder()
+        final boolean isMixin() {
+            return false;
+        }
+    }
+
+    private static final class AnydataNormalization extends AbstractOpaqueNormalization {
+        AnydataNormalization(final AnydataSchemaNode schema) {
+            super(schema);
+        }
+
+        @Override
+        NormalizedNode create(final PathArgument first, final Iterator<PathArgument> others,
+                final Optional<NormalizedNode> deepestChild) {
+            checkState(deepestChild.isPresent(), "Cannot instantiate anydata node without a value");
+            final NormalizedNode child = deepestChild.get();
+            checkState(child instanceof AnydataNode, "Invalid child %s", child);
+            return createAnydata((AnydataNode<?>) child);
+        }
+
+        private <T> AnydataNode<T> createAnydata(final AnydataNode<T> child) {
+            return Builders.anydataBuilder(child.bodyObjectModel()).withValue(child.body())
+            .withNodeIdentifier(getIdentifier()).build();
+        }
+    }
+
+    private static final class AnyXmlNormalization extends AbstractOpaqueNormalization {
+        AnyXmlNormalization(final AnyxmlSchemaNode schema) {
+            super(schema);
+        }
+
+        @Override
+        NormalizedNode create(final PathArgument first, final Iterator<PathArgument> others,
+                final Optional<NormalizedNode> deepestChild) {
+            final NormalizedNodeBuilder<NodeIdentifier, DOMSource, DOMSourceAnyxmlNode> builder =
+                    Builders.anyXmlBuilder()
                     .withNodeIdentifier(getIdentifier());
             if (deepestChild.isPresent()) {
-                final NormalizedNode<?, ?> child = deepestChild.get();
-                checkState(child instanceof AnyXmlNode);
-                builder.withValue(((AnyXmlNode) child).getValue());
+                final NormalizedNode child = deepestChild.get();
+                checkState(child instanceof DOMSourceAnyxmlNode, "Invalid child %s", child);
+                builder.withValue(((DOMSourceAnyxmlNode) child).body());
             }
 
             return builder.build();
         }
-
-        @Override
-        boolean isMixin() {
-            return false;
-        }
     }
 
     private static Optional<DataSchemaNode> findChildSchemaNode(final DataNodeContainer parent, final QName child) {
@@ -135,7 +158,7 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
             findChoice(Iterables.filter(parent.getChildNodes(), ChoiceSchemaNode.class), child));
     }
 
-    static InstanceIdToNodes<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
+    static @Nullable InstanceIdToNodes<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
         final Optional<DataSchemaNode> potential = findChildSchemaNode(schema, child);
         checkArgument(potential.isPresent(),
                 "Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema,
@@ -149,9 +172,9 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
         return fromDataSchemaNode(result);
     }
 
-    private static ChoiceSchemaNode findChoice(final Iterable<ChoiceSchemaNode> choices, final QName child) {
+    private static @Nullable ChoiceSchemaNode findChoice(final Iterable<ChoiceSchemaNode> choices, final QName child) {
         for (final ChoiceSchemaNode choice : choices) {
-            for (final CaseSchemaNode caze : choice.getCases().values()) {
+            for (final CaseSchemaNode caze : choice.getCases()) {
                 if (findChildSchemaNode(caze, child).isPresent()) {
                     return choice;
                 }
@@ -168,7 +191,7 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
      * otherwise returns a SchemaPathUtil for child as
      * call for {@link #fromDataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode)}.
      */
-    private static InstanceIdToNodes<?> fromAugmentation(final DataNodeContainer parent,
+    private static @Nullable InstanceIdToNodes<?> fromAugmentation(final DataNodeContainer parent,
             final AugmentationTarget parentAug, final DataSchemaNode child) {
         for (final AugmentationSchemaNode aug : parentAug.getAvailableAugmentations()) {
             final Optional<DataSchemaNode> potential = aug.findDataChildByName(child.getQName());
@@ -179,9 +202,9 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
         return fromDataSchemaNode(child);
     }
 
-    static InstanceIdToNodes<?> fromDataSchemaNode(final DataSchemaNode potential) {
-        if (potential instanceof ContainerSchemaNode) {
-            return new InstanceIdToCompositeNodes.ContainerTransformation((ContainerSchemaNode) potential);
+    static @Nullable InstanceIdToNodes<?> fromDataSchemaNode(final DataSchemaNode potential) {
+        if (potential instanceof ContainerLike) {
+            return new InstanceIdToCompositeNodes.ContainerTransformation((ContainerLike) potential);
         } else if (potential instanceof ListSchemaNode) {
             return fromListSchemaNode((ListSchemaNode) potential);
         } else if (potential instanceof LeafSchemaNode) {
@@ -190,8 +213,10 @@ abstract class InstanceIdToNodes<T extends PathArgument> implements Identifiable
             return new InstanceIdToCompositeNodes.ChoiceNodeNormalization((ChoiceSchemaNode) potential);
         } else if (potential instanceof LeafListSchemaNode) {
             return fromLeafListSchemaNode((LeafListSchemaNode) potential);
-        } else if (potential instanceof AnyXmlSchemaNode) {
-            return new AnyXmlNormalization((AnyXmlSchemaNode) potential);
+        } else if (potential instanceof AnydataSchemaNode) {
+            return new AnydataNormalization((AnydataSchemaNode) potential);
+        } else if (potential instanceof AnyxmlSchemaNode) {
+            return new AnyXmlNormalization((AnyxmlSchemaNode) potential);
         }
         return null;
     }