BUG 2868: Update iana-if-type with RFC 7224
[mdsal.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / InstanceIdentifierCodecImpl.java
index 6dbb0f271aecadc302afe7f9dc132a9284aaabf5..aeda45c9904f30634b031f8169e76acc46347e53 100644 (file)
@@ -7,34 +7,30 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
-import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
-import org.eclipse.xtext.xbase.lib.Functions.Function0;
 import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.sal.binding.generator.impl.CodecTypeUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-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.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
@@ -49,6 +45,8 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
 
     private final CodecRegistry codecRegistry;
 
+    private final Map<Class<?>,Set<List<QName>>> augmentationAdapted = new WeakHashMap<>();
+
     private final Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = Collections
             .synchronizedMap(new WeakHashMap<Class<?>, Map<List<QName>, Class<?>>>());
 
@@ -58,12 +56,12 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
 
     @Override
     public InstanceIdentifier<? extends Object> deserialize(
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier input) {
         Class<?> baType = null;
-        List<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument> biArgs = input.getPath();
-        List<QName> scannedPath = new ArrayList<>(biArgs.size());
-        List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size());
-        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg : biArgs) {
+        Iterable<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> biArgs = input.getPathArguments();
+        List<QName> scannedPath = new ArrayList<>();
+        List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>();
+        for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument biArg : biArgs) {
 
             scannedPath.add(biArg.getNodeType());
             org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument baArg = deserializePathArgument(
@@ -73,6 +71,7 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
             }
             Map<List<QName>, Class<?>> injectAugment = classToPreviousAugment.get(baType);
             if (injectAugment != null) {
+                @SuppressWarnings("unchecked")
                 Class<? extends DataObject> augment = (Class<? extends DataObject>) injectAugment.get(scannedPath);
                 if (augment != null) {
                     baArgs.add(new Item(augment));
@@ -80,24 +79,36 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
             }
             baArgs.add(baArg);
         }
-        InstanceIdentifier ret = InstanceIdentifier.create(baArgs);
+        InstanceIdentifier<?> ret = InstanceIdentifier.create(baArgs);
         LOG.debug("DOM Instance Identifier {} deserialized to {}", input, ret);
         return ret;
     }
 
-    private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
+    @Override
+    public InstanceIdentifier<? extends Object> deserialize(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier input,
+            final InstanceIdentifier<?> bindingIdentifier) {
+        return deserialize(input);
+    }
+
+    private InstanceIdentifier.PathArgument deserializeNodeIdentifier(
             final NodeIdentifier argument, final List<QName> processedPath) {
+        @SuppressWarnings("rawtypes")
         final Class cls = codecRegistry.getClassForPath(processedPath);
+        @SuppressWarnings("unchecked")
         Item<DataObject> item = new Item<>(cls);
         return item;
     }
 
-    private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
+    private InstanceIdentifier.PathArgument deserializeNodeIdentifierWithPrecicates(
             final NodeIdentifierWithPredicates argument, final List<QName> processedPath) {
+        @SuppressWarnings("rawtypes")
         final Class type = codecRegistry.getClassForPath(processedPath);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
         final IdentifierCodec codec = codecRegistry
                 .<Identifiable<? extends Object>> getIdentifierCodecForIdentifiable(type);
         CompositeNode _compositeNode = this.toCompositeNode(argument);
+        @SuppressWarnings("unchecked")
         ValueWithQName<CompositeNode> deserialize = codec.deserialize(_compositeNode);
         Object value = null;
         if (deserialize != null) {
@@ -106,7 +117,7 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return CodecTypeUtils.newIdentifiableItem(type, value);
     }
 
-    public CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
+    public CompositeNode toCompositeNode(final NodeIdentifierWithPredicates predicates) {
         Set<Map.Entry<QName, Object>> keyValues = predicates.getKeyValues().entrySet();
         List<Node<?>> values = new ArrayList<>(keyValues.size());
         for (Map.Entry<QName, Object> keyValue : keyValues) {
@@ -116,46 +127,59 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
     }
 
     @Override
-    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(InstanceIdentifier<?> input) {
+    public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier serialize(final InstanceIdentifier<?> input) {
         Class<?> previousAugmentation = null;
-        List<InstanceIdentifier.PathArgument> pathArgs = input.getPath();
+        Iterable<InstanceIdentifier.PathArgument> pathArgs = input.getPathArguments();
         QName previousQName = null;
-        List<PathArgument> components = new ArrayList<>(pathArgs.size());
-        List<QName> qnamePath = new ArrayList<>(pathArgs.size());
+        List<PathArgument> components = new ArrayList<>();
+        List<QName> qnamePath = new ArrayList<>();
         for (InstanceIdentifier.PathArgument baArg : pathArgs) {
-
             if (!Augmentation.class.isAssignableFrom(baArg.getType())) {
-                org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg = serializePathArgument(
-                        baArg, previousQName);
-                previousQName = biArg.getNodeType();
+                PathArgument biArg = serializePathArgumentAndUpdateMapping(qnamePath, baArg, previousQName,previousAugmentation);
                 components.add(biArg);
                 qnamePath.add(biArg.getNodeType());
-                ImmutableList<QName> immutableList = ImmutableList.copyOf(qnamePath);
-                codecRegistry.putPathToClass(immutableList, baArg.getType());
-                if (previousAugmentation != null) {
-                    updateAugmentationInjection(baArg.getType(), immutableList, previousAugmentation);
-                }
+                previousQName = biArg.getNodeType();
                 previousAugmentation = null;
             } else {
                 previousQName = codecRegistry.getQNameForAugmentation(baArg.getType());
                 previousAugmentation = baArg.getType();
+                ensureAugmentation(qnamePath,previousQName,baArg.getType());
             }
         }
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
-                components);
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier ret =
+                org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(components);
         LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}", input, ret);
         return ret;
     }
 
-    public Class<? extends Object> updateAugmentationInjection(Class<? extends DataObject> class1,
-            ImmutableList<QName> list, Class<?> augmentation) {
+    private synchronized void ensureAugmentation(final List<QName> augPath, final QName augQName, final Class<? extends DataObject> type) {
+        Set<List<QName>> augPotential = augmentationAdapted.get(type);
+        if(augPotential == null) {
+            augPotential = new HashSet<>();
+            augmentationAdapted.put(type, augPotential);
+        }
+        ImmutableList<QName> augTargetPath = ImmutableList.copyOf(augPath);
+        if(augPotential.contains(augPath)) {
+            return;
+        }
+
+        for(Class<? extends DataObject> child : BindingReflections.getChildrenClasses(type)) {
+            Item<? extends DataObject> baArg = new Item<>(child);
+            PathArgument biArg = serializePathArgumentAndUpdateMapping(augPath, baArg, augQName,type);
+        }
+        augPotential.add(augTargetPath);
+    }
+
+
+    public Class<? extends Object> updateAugmentationInjection(final Class<? extends DataObject> class1,
+            final List<QName> list, final Class<?> augmentation) {
         if (classToPreviousAugment.get(class1) == null) {
             classToPreviousAugment.put(class1, new ConcurrentHashMap<List<QName>, Class<?>>());
         }
         return classToPreviousAugment.get(class1).put(list, augmentation);
     }
 
-    private PathArgument _serializePathArgument(Item<?> argument, QName previousQname) {
+    private PathArgument serializeItem(final Item<?> argument, final QName previousQname) {
         Class<?> type = argument.getType();
         QName qname = BindingReflections.findQName(type);
         if (previousQname == null || (BindingReflections.isAugmentationChild(argument.getType()))) {
@@ -164,16 +188,21 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return new NodeIdentifier(QName.create(previousQname, qname.getLocalName()));
     }
 
-    private PathArgument _serializePathArgument(IdentifiableItem argument, QName previousQname) {
-        Map<QName, Object> predicates = new HashMap<>();
+    private PathArgument serializeIdentifiableItem(final IdentifiableItem<?,?> argument, final QName previousQname) {
+        @SuppressWarnings("rawtypes")
         Class type = argument.getType();
+        @SuppressWarnings("unchecked")
         IdentifierCodec<? extends Object> keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
         QName qname = BindingReflections.findQName(type);
         if (previousQname != null && !(BindingReflections.isAugmentationChild(argument.getType()))) {
             qname = QName.create(previousQname, qname.getLocalName());
         }
+        @SuppressWarnings({ "rawtypes", "unchecked" })
         ValueWithQName combinedInput = new ValueWithQName(previousQname, argument.getKey());
+        @SuppressWarnings("unchecked")
         CompositeNode compositeOutput = keyCodec.serialize(combinedInput);
+
+        final Map<QName, Object> predicates = new LinkedHashMap<>();
         for (Node<?> outputValue : compositeOutput.getValue()) {
             predicates.put(outputValue.getNodeType(), outputValue.getValue());
         }
@@ -186,26 +215,40 @@ public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
     private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(
             final PathArgument argument, final List<QName> processedPath) {
         if (argument instanceof NodeIdentifier) {
-            return _deserializePathArgument((NodeIdentifier) argument, processedPath);
+            return deserializeNodeIdentifier((NodeIdentifier) argument, processedPath);
         } else if (argument instanceof NodeIdentifierWithPredicates) {
-            return _deserializePathArgument((NodeIdentifierWithPredicates) argument, processedPath);
+            return deserializeNodeIdentifierWithPrecicates((NodeIdentifierWithPredicates) argument, processedPath);
         } else {
             throw new IllegalArgumentException("Unhandled parameter types: "
                     + Arrays.<Object> asList(argument, processedPath).toString());
         }
     }
 
+    private PathArgument serializePathArgumentAndUpdateMapping(final List<QName> parentPath, final InstanceIdentifier.PathArgument baArg, final QName previousQName, final Class<?> previousAugmentation) {
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument biArg = serializePathArgument(baArg, previousQName);
+        List<QName> qnamePath = new ArrayList<>(parentPath);
+        qnamePath.add(biArg.getNodeType());
+        ImmutableList<QName> currentPath = ImmutableList.copyOf(qnamePath);
+        codecRegistry.putPathToClass(currentPath, baArg.getType());
+        if (previousAugmentation != null) {
+            updateAugmentationInjection(baArg.getType(), currentPath, previousAugmentation);
+        }
+        return biArg;
+    }
+
     private PathArgument serializePathArgument(
-            final org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument argument,
+            final InstanceIdentifier.PathArgument argument,
             final QName previousQname) {
         if (argument instanceof IdentifiableItem) {
-            return _serializePathArgument((IdentifiableItem) argument, previousQname);
+            return serializeIdentifiableItem((IdentifiableItem<?,?>) argument, previousQname);
         } else if (argument instanceof Item) {
-            return _serializePathArgument((Item<?>) argument, previousQname);
+            return serializeItem((Item<?>) argument, previousQname);
         } else {
             throw new IllegalArgumentException("Unhandled parameter types: "
                     + Arrays.<Object> asList(argument, previousQname).toString());
         }
     }
 
+
+
 }