BUG 484 Anyxml normalized node
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / util / compat / DataNormalizer.java
index 28b2bde26d31e4558b5f716666147983446811cc..ec8ce6ecd5a96e628d2883ab38f24aaab383095a 100644 (file)
@@ -1,36 +1,41 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.md.sal.common.impl.util.compat;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Map;
-
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
 public class DataNormalizer {
 
     private final DataNormalizationOperation<?> operation;
@@ -44,38 +49,59 @@ public class DataNormalizer {
 
         DataNormalizationOperation<?> currentOp = operation;
         Iterator<PathArgument> arguments = legacy.getPath().iterator();
-        while ( arguments.hasNext() ) {
-            PathArgument legacyArg = arguments.next();
-            currentOp = currentOp.getChild(legacyArg);
-            checkArgument(currentOp != null, "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",legacy,normalizedArgs.build());
-            while (currentOp.isMixin()) {
-                normalizedArgs.add(currentOp.getIdentifier());
-                currentOp = currentOp.getChild(legacyArg.getNodeType());
-            }
-            if(arguments.hasNext() || (!currentOp.isKeyedEntry() || legacyArg instanceof NodeIdentifierWithPredicates || legacyArg instanceof NodeWithValue)) {
+
+        try {
+            while (arguments.hasNext()) {
+                PathArgument legacyArg = arguments.next();
+                currentOp = currentOp.getChild(legacyArg);
+                checkArgument(currentOp != null,
+                        "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",
+                        legacy, normalizedArgs.build());
+                while (currentOp.isMixin()) {
+                    normalizedArgs.add(currentOp.getIdentifier());
+                    currentOp = currentOp.getChild(legacyArg.getNodeType());
+                }
                 normalizedArgs.add(legacyArg);
             }
+        } catch (DataNormalizationException e) {
+            throw new IllegalArgumentException(String.format("Failed to normalize path %s", legacy), e);
         }
+
         return new InstanceIdentifier(normalizedArgs.build());
     }
 
-    public Map.Entry<InstanceIdentifier,NormalizedNode<?, ?>> toNormalized(final Map.Entry<InstanceIdentifier,CompositeNode> legacy) {
+    public Map.Entry<InstanceIdentifier, NormalizedNode<?, ?>> toNormalized(
+            final Map.Entry<InstanceIdentifier, CompositeNode> legacy) {
         return toNormalized(legacy.getKey(), legacy.getValue());
     }
 
-    public Map.Entry<InstanceIdentifier,NormalizedNode<?, ?>> toNormalized(final InstanceIdentifier legacyPath, final CompositeNode legacyData) {
+    public Map.Entry<InstanceIdentifier, NormalizedNode<?, ?>> toNormalized(final InstanceIdentifier legacyPath,
+            final CompositeNode legacyData) {
 
         InstanceIdentifier normalizedPath = toNormalized(legacyPath);
 
         DataNormalizationOperation<?> currentOp = operation;
         for (PathArgument arg : normalizedPath.getPath()) {
-            currentOp = currentOp.getChild(arg);
+            try {
+                currentOp = currentOp.getChild(arg);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Failed to validate normalized path %s",
+                        normalizedPath), e);
+            }
         }
-        // Write Augmentaiton data resolution
-        if (legacyData.getChildren().size() == 1) {
-            DataNormalizationOperation<?> potentialOp = currentOp.getChild(legacyData.getChildren().get(0)
-                    .getNodeType());
-            if(potentialOp.getIdentifier() instanceof AugmentationIdentifier) {
+
+        // Write Augmentation data resolution
+        if (legacyData.getValue().size() == 1) {
+            final DataNormalizationOperation<?> potentialOp;
+
+            try {
+                final QName childType = legacyData.getValue().get(0).getNodeType();
+                potentialOp = currentOp.getChild(childType);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Failed to get child operation for %s", legacyData), e);
+            }
+
+            if (potentialOp.getIdentifier() instanceof AugmentationIdentifier) {
                 currentOp = potentialOp;
                 ArrayList<PathArgument> reworkedArgs = new ArrayList<>(normalizedPath.getPath());
                 reworkedArgs.add(potentialOp.getIdentifier());
@@ -85,28 +111,19 @@ public class DataNormalizer {
 
         Preconditions.checkArgument(currentOp != null,
                 "Instance Identifier %s does not reference correct schema Node.", normalizedPath);
-        return new AbstractMap.SimpleEntry<InstanceIdentifier,NormalizedNode<?, ?>>(normalizedPath,currentOp.normalize(legacyData));
+        return new AbstractMap.SimpleEntry<InstanceIdentifier, NormalizedNode<?, ?>>(normalizedPath,
+                currentOp.normalize(legacyData));
     }
 
-    public InstanceIdentifier toLegacy(final InstanceIdentifier normalized) {
+    public InstanceIdentifier toLegacy(final InstanceIdentifier normalized) throws DataNormalizationException {
         ImmutableList.Builder<PathArgument> legacyArgs = ImmutableList.builder();
         PathArgument previous = null;
+        DataNormalizationOperation<?> currentOp = operation;
         for (PathArgument normalizedArg : normalized.getPath()) {
-            if (normalizedArg instanceof NodeIdentifier) {
-                if (previous != null) {
-                    legacyArgs.add(previous);
-                }
-                previous = normalizedArg;
-            } else if (normalizedArg instanceof NodeIdentifierWithPredicates) {
-                // We skip previous node, which was mixin.
-                previous = normalizedArg;
-            } else if (normalizedArg instanceof AugmentationIdentifier) {
-                // We ignore argument
+            currentOp = currentOp.getChild(normalizedArg);
+            if(!currentOp.isMixin()) {
+                legacyArgs.add(normalizedArg);
             }
-            // FIXME : Add option for reading choice
-        }
-        if (previous != null) {
-            legacyArgs.add(previous);
         }
         return new InstanceIdentifier(legacyArgs.build());
     }
@@ -116,6 +133,9 @@ public class DataNormalizer {
         // DataContainerNode<?>,"Node object %s, %s should be of type DataContainerNode",normalizedPath,normalizedData);
         if (normalizedData instanceof DataContainerNode<?>) {
             return toLegacyFromDataContainer((DataContainerNode<?>) normalizedData);
+        } else if (normalizedData instanceof AnyXmlNode) {
+            Node<?> value = ((AnyXmlNode) normalizedData).getValue();
+            return value instanceof CompositeNode ? (CompositeNode)value : null;
         }
         return null;
     }
@@ -123,9 +143,8 @@ public class DataNormalizer {
     public static Node<?> toLegacy(final NormalizedNode<?, ?> node) {
         if (node instanceof MixinNode) {
             /**
-             * Direct reading of MixinNodes is not supported,
-             * since it is not possible in legacy APIs create pointer
-             * to Mixin Nodes.
+             * Direct reading of MixinNodes is not supported, since it is not
+             * possible in legacy APIs create pointer to Mixin Nodes.
              *
              */
             return null;
@@ -133,6 +152,8 @@ public class DataNormalizer {
 
         if (node instanceof DataContainerNode<?>) {
             return toLegacyFromDataContainer((DataContainerNode<?>) node);
+        } else if (node instanceof AnyXmlNode) {
+            return ((AnyXmlNode) node).getValue();
         }
         return toLegacySimple(node);
 
@@ -149,6 +170,8 @@ public class DataNormalizer {
         for (NormalizedNode<?, ?> child : node.getValue()) {
             if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
                 builder.addAll(toLegacyNodesFromMixin((NormalizedNodeContainer) child));
+            } else if( child instanceof UnkeyedListNode) {
+                builder.addAll(toLegacyNodesFromUnkeyedList((UnkeyedListNode) child));
             } else {
                 addToBuilder(builder, toLegacy(child));
             }
@@ -156,6 +179,14 @@ public class DataNormalizer {
         return builder.toInstance();
     }
 
+    private static Iterable<? extends Node<?>> toLegacyNodesFromUnkeyedList(final UnkeyedListNode mixin) {
+        ArrayList<Node<?>> ret = new ArrayList<>();
+        for (NormalizedNode<?, ?> child : mixin.getValue()) {
+            ret.add(toLegacy(child));
+        }
+        return FluentIterable.from(ret).filter(Predicates.notNull());
+    }
+
     private static void addToBuilder(final CompositeNodeBuilder<ImmutableCompositeNode> builder, final Node<?> legacy) {
         if (legacy != null) {
             builder.add(legacy);
@@ -167,19 +198,13 @@ public class DataNormalizer {
             final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> mixin) {
         ArrayList<Node<?>> ret = new ArrayList<>();
         for (NormalizedNode<?, ?> child : mixin.getValue()) {
-            if(child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
-                Iterables.addAll(ret,toLegacyNodesFromMixin((NormalizedNodeContainer) child));
+            if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
+                Iterables.addAll(ret, toLegacyNodesFromMixin((NormalizedNodeContainer) child));
             } else {
                 ret.add(toLegacy(child));
             }
         }
-        return FluentIterable.from(ret).filter(new Predicate<Node<?>>() {
-
-            @Override
-            public boolean apply(final Node<?> input) {
-                return input != null;
-            }
-        });
+        return FluentIterable.from(ret).filter(Predicates.notNull());
     }
 
     public DataNormalizationOperation<?> getRootOperation() {