Created sal-clustering-commons and moved
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / util / InstanceIdentifierUtils.java
diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/util/InstanceIdentifierUtils.java
new file mode 100644 (file)
index 0000000..55cb341
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ *
+ *  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.cluster.datastore.util;
+
+import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class contains utility methods for converting an MD-SAL
+ * YangInstanceIdentifier to and from other representations.
+ * <p>
+ * The representations convered for now are,
+ *
+ * <ul>
+ *     <li>String</li>
+ *     <li>Protocol Buffer</li>
+ * </ul>
+ */
+public class InstanceIdentifierUtils {
+
+    protected static final Logger logger = LoggerFactory
+        .getLogger(InstanceIdentifierUtils.class);
+
+    @Deprecated
+    public static YangInstanceIdentifier from(String path) {
+        String[] ids = path.split("/");
+
+        List<YangInstanceIdentifier.PathArgument> pathArguments =
+            new ArrayList<>();
+        for (String nodeId : ids) {
+            if (!"".equals(nodeId)) {
+                pathArguments
+                    .add(NodeIdentifierFactory.getArgument(nodeId));
+            }
+        }
+        final YangInstanceIdentifier instanceIdentifier =
+            YangInstanceIdentifier.create(pathArguments);
+        return instanceIdentifier;
+    }
+
+
+    /**
+     * Convert an MD-SAL YangInstanceIdentifier into a protocol buffer version of it
+     *
+     * @param path an MD-SAL YangInstanceIdentifier
+     * @return a protocol buffer version of the MD-SAL YangInstanceIdentifier
+     */
+    public static NormalizedNodeMessages.InstanceIdentifier toSerializable(YangInstanceIdentifier path){
+        NormalizedNodeMessages.InstanceIdentifier.Builder builder =
+            NormalizedNodeMessages.InstanceIdentifier.newBuilder();
+
+        try {
+
+            for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument pathArgument : path
+                .getPathArguments()) {
+
+                String nodeType = "";
+                if(!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)){
+                    nodeType = pathArgument.getNodeType().toString();
+                }
+
+                NormalizedNodeMessages.PathArgument serializablePathArgument =
+                    NormalizedNodeMessages.PathArgument.newBuilder()
+                        .setValue(pathArgument.toString())
+                        .setType(pathArgument.getClass().getSimpleName())
+                        .setNodeType(NormalizedNodeMessages.QName.newBuilder()
+                            .setValue(nodeType))
+                        .addAllAttributes(getPathArgumentAttributes(
+                            pathArgument))
+                        .build();
+
+                builder.addArguments(serializablePathArgument);
+            }
+
+        } catch(Exception e){
+            logger.error("An exception occurred", e);
+        }
+        return builder.build();
+    }
+
+
+    /**
+     * Convert a protocol buffer version of the MD-SAL YangInstanceIdentifier into
+     * the MD-SAL version of the YangInstanceIdentifier
+     *
+     * @param path a protocol buffer version of the MD-SAL YangInstanceIdentifier
+     * @return  an MD-SAL YangInstanceIdentifier
+     */
+    public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path){
+
+        List<YangInstanceIdentifier.PathArgument> pathArguments =
+            new ArrayList<>();
+
+        for(NormalizedNodeMessages.PathArgument pathArgument : path.getArgumentsList()){
+
+            pathArguments
+                .add(parsePathArgument(pathArgument));
+
+        }
+
+        final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.create(pathArguments);
+
+        return instanceIdentifier;
+    }
+
+    /**
+     * Take the various attributes of a PathArgument and package them up as
+     * protocol buffer attributes.
+     * <p>
+     *
+     * PathArguments have 4 subtypes and each of the various subtypes have
+     * different attributes
+     * <ul>
+     *     <li>
+     *         NodeIdentifier is the most basic PathArgument. It is used for
+     *         ContainerNode, LeafNode etc and has no attributes
+     *     </li>
+     *     <li>
+     *         NodeWithValue has only a single attribute. It is used for
+     *         LeafListEntryNodes and the attribute it contains is the value
+     *         of the entry
+     *     </li>
+     *     <li>
+     *         NodeIdentifierWithPredicates has a map of attributes.
+     *         It is used to represent a ListItemNode. Each entry
+     *         in the map of attributes represents the key and value of the
+     *         keys in that entry.
+     *     </li>
+     *     <li>
+     *         AugmentationIdentifier has a list of unnamed attributes. Each
+     *         attribute represents the possible children that can go within
+     *         an augmentation entry.
+     *     </li>
+     * </ul>
+     * @param pathArgument
+     * @return
+     */
+    private static Iterable<? extends NormalizedNodeMessages.Attribute> getPathArgumentAttributes(
+        YangInstanceIdentifier.PathArgument pathArgument) {
+        List<NormalizedNodeMessages.Attribute> attributes = new ArrayList<>();
+
+
+
+        if (pathArgument instanceof YangInstanceIdentifier.NodeWithValue) {
+            YangInstanceIdentifier.NodeWithValue identifier
+                = (YangInstanceIdentifier.NodeWithValue) pathArgument;
+
+            NormalizedNodeMessages.Attribute attribute =
+                NormalizedNodeMessages.Attribute.newBuilder()
+                    .setName("name")
+                    .setValue(identifier.getValue().toString())
+                    .setType(identifier.getValue().getClass().getSimpleName())
+                    .build();
+
+            attributes.add(attribute);
+        } else if (pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
+            YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
+                = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
+
+            for (QName key : identifier.getKeyValues().keySet()) {
+                Object value = identifier.getKeyValues().get(key);
+                NormalizedNodeMessages.Attribute attribute =
+                    NormalizedNodeMessages.Attribute.newBuilder()
+                        .setName(key.toString())
+                        .setValue(value.toString())
+                        .setType(value.getClass().getSimpleName())
+                        .build();
+
+                attributes.add(attribute);
+
+            }
+
+        } else if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+            YangInstanceIdentifier.AugmentationIdentifier identifier
+                = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
+
+            for (QName key : identifier.getPossibleChildNames()) {
+                Object value = key;
+                NormalizedNodeMessages.Attribute attribute =
+                    NormalizedNodeMessages.Attribute.newBuilder()
+                        .setName(key.toString())
+                        .setValue(value.toString())
+                        .setType(value.getClass().getSimpleName())
+                        .build();
+
+                attributes.add(attribute);
+
+            }
+        }
+
+        return attributes;
+    }
+
+
+    /**
+     * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
+     *
+     * @param pathArgument protocol buffer PathArgument
+     * @return MD-SAL PathArgument
+     */
+    private static YangInstanceIdentifier.PathArgument parsePathArgument(NormalizedNodeMessages.PathArgument pathArgument) {
+        if (YangInstanceIdentifier.NodeWithValue.class.getSimpleName().equals(pathArgument.getType())) {
+
+            YangInstanceIdentifier.NodeWithValue nodeWithValue =
+                new YangInstanceIdentifier.NodeWithValue(
+                    QName.create(pathArgument.getNodeType().getValue()),
+                    parseAttribute(pathArgument.getAttributes(0)));
+
+            return nodeWithValue;
+
+        } else if(YangInstanceIdentifier.NodeIdentifierWithPredicates.class.getSimpleName().equals(pathArgument.getType())){
+
+            YangInstanceIdentifier.NodeIdentifierWithPredicates
+                nodeIdentifierWithPredicates =
+                new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                    QName.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
+
+            return nodeIdentifierWithPredicates;
+
+        } else if(YangInstanceIdentifier.AugmentationIdentifier.class.getSimpleName().equals(pathArgument.getType())){
+
+            Set<QName> qNameSet = new HashSet<>();
+
+            for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
+                qNameSet.add(QName.create(attribute.getValue()));
+            }
+
+            return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
+        }
+
+        return NodeIdentifierFactory.getArgument(pathArgument.getValue());
+    }
+
+    private static Map<QName, Object> toAttributesMap(
+        List<NormalizedNodeMessages.Attribute> attributesList) {
+
+        Map<QName, Object> map = new HashMap<>();
+
+        for(NormalizedNodeMessages.Attribute attribute : attributesList){
+            String name = attribute.getName();
+            Object value = parseAttribute(attribute);
+
+            map.put(QName.create(name), value);
+        }
+
+        return map;
+    }
+
+    /**
+     * FIXME: This method only covers a subset of values that may go in an InstanceIdentifier
+     *
+     * @param attribute
+     * @return
+     */
+    private static Object parseAttribute(NormalizedNodeMessages.Attribute attribute){
+        if(Short.class.getSimpleName().equals(attribute.getType())) {
+            return Short.parseShort(attribute.getValue());
+        } else if(Long.class.getSimpleName().equals(attribute.getType())){
+            return Long.parseLong(attribute.getValue());
+        } else if(Boolean.class.getSimpleName().equals(attribute.getType())){
+            return Boolean.parseBoolean(attribute.getValue());
+        } else if(Integer.class.getSimpleName().equals(attribute.getType())){
+            return Integer.parseInt(attribute.getValue());
+        }
+
+        return attribute.getValue();
+    }
+}