Remove explicit default super-constructor calls
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / builder / impl / ImmutableMapEntryNodeBuilder.java
index 90e36f736a11cb1b3c4e546b67a3aef1f4f4c522..59af23fa5fdfbc57d42eb0142a83ce763583598f 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
-import java.util.List;
+import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.Map;
-
+import java.util.Map.Entry;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ImmutableMapEntryNodeBuilder
-        extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
-
-    protected final Map<QName, InstanceIdentifier.PathArgument> childrenQNamesToPaths;
+        extends AbstractImmutableDataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> {
+    private static final Logger LOG = LoggerFactory.getLogger(ImmutableMapEntryNodeBuilder.class);
+    protected final Map<QName, PathArgument> childrenQNamesToPaths;
 
     protected ImmutableMapEntryNodeBuilder() {
-        this.childrenQNamesToPaths = Maps.newLinkedHashMap();
+        this.childrenQNamesToPaths = new LinkedHashMap<>();
+    }
+
+    protected ImmutableMapEntryNodeBuilder(final int sizeHint) {
+        super(sizeHint);
+        this.childrenQNamesToPaths = new LinkedHashMap<>(sizeHint);
+    }
+
+    protected ImmutableMapEntryNodeBuilder(final ImmutableMapEntryNode node) {
+        super(node);
+        this.childrenQNamesToPaths = new LinkedHashMap<>();
+        fillQnames(node.getValue(), childrenQNamesToPaths);
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create() {
+    public static DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> create() {
         return new ImmutableMapEntryNodeBuilder();
     }
 
-    // FIXME, find better solution than 2 maps (map from QName to Child ?)
+    public static DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> create(final int sizeHint) {
+        return new ImmutableMapEntryNodeBuilder(sizeHint);
+    }
 
-    @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
-        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : value) {
-            this.childrenQNamesToPaths.put(childId.getNodeType(), childId.getIdentifier());
+    public static DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> create(
+            final MapEntryNode node) {
+        if (!(node instanceof ImmutableMapEntryNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
         }
-        return super.withValue(value);
+
+        return new ImmutableMapEntryNodeBuilder((ImmutableMapEntryNode)node);
     }
 
-    @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(DataContainerChild<?, ?> child) {
-        childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
-        return super.withChild(child);
+    private static void fillQnames(final Iterable<DataContainerChild<? extends PathArgument, ?>> iterable,
+            final Map<QName, PathArgument> out) {
+        for (final DataContainerChild<? extends PathArgument, ?> childId : iterable) {
+            final PathArgument identifier = childId.getIdentifier();
+
+            // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+            if (isAugment(identifier)) {
+                continue;
+            }
+
+            out.put(childId.getNodeType(), identifier);
+        }
     }
 
-    public MapEntryNode build() {
-        checkKeys();
-        return new ImmutableMapEntryNode(nodeIdentifier, value);
+
+    @Override
+    public DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> withValue(
+            final Collection<DataContainerChild<? extends PathArgument, ?>> value) {
+        fillQnames(value, childrenQNamesToPaths);
+        return super.withValue(value);
     }
 
-    private void checkKeys() {
-        for (QName keyQName : nodeIdentifier.getKeyValues().keySet()) {
+    private static boolean isAugment(final PathArgument identifier) {
+        return identifier instanceof AugmentationIdentifier;
+    }
 
-            InstanceIdentifier.PathArgument childNodePath = childrenQNamesToPaths.get(keyQName);
-            DataContainerChild<?, ?> childNode = value.get(childNodePath);
+    @Override
+    public DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> withChild(
+            final DataContainerChild<?, ?> child) {
+        // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+        if (!isAugment(child.getIdentifier())) {
+            childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+        }
 
-            Preconditions.checkNotNull(childNode, "Key child node: %s, not present", keyQName);
+        return super.withChild(child);
+    }
 
-            Object actualValue = nodeIdentifier.getKeyValues().get(keyQName);
-            Object expectedValue = childNode.getValue();
-            Preconditions.checkArgument(expectedValue.equals(actualValue),
-                    "Key child node with unexpected value, is: %s, should be: %s", actualValue, expectedValue);
+    @Override
+    public MapEntryNode build() {
+        for (final Entry<QName, Object> key : getNodeIdentifier().getKeyValues().entrySet()) {
+            final DataContainerChild<?, ?> childNode = getChild(childrenQNamesToPaths.get(key.getKey()));
+
+            // We have enough information to fill-in missing leaf nodes, so let's do that
+            if (childNode == null) {
+                LeafNode<Object> leaf = ImmutableNodes.leafNode(key.getKey(), key.getValue());
+                LOG.debug("Adding leaf {} implied by key {}", leaf, key);
+                withChild(leaf);
+            } else {
+                DataValidationException.checkListKey(getNodeIdentifier(), key.getKey(), key.getValue(),
+                    childNode.getValue());
+            }
         }
+
+        return new ImmutableMapEntryNode(getNodeIdentifier(), buildValue(), getAttributes());
     }
 
-    static final class ImmutableMapEntryNode extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifierWithPredicates> implements MapEntryNode {
+    private static final class ImmutableMapEntryNode
+            extends AbstractImmutableDataContainerAttrNode<NodeIdentifierWithPredicates> implements MapEntryNode {
 
-        ImmutableMapEntryNode(InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier,
-                              Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
-            super(children, nodeIdentifier);
+        ImmutableMapEntryNode(final NodeIdentifierWithPredicates nodeIdentifier,
+                final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children,
+                final Map<QName, String> attributes) {
+            super(children, nodeIdentifier, attributes);
         }
     }
 }