[ONOS-5907] Resource identifier additional utilities.

Change-Id: Ia7b005e1c6be6c168c6536d4779f9f7fffc176c2
diff --git a/model/src/main/java/org/onosproject/yang/model/KeyLeaf.java b/model/src/main/java/org/onosproject/yang/model/KeyLeaf.java
index 5bc0243..f9cb0bb 100644
--- a/model/src/main/java/org/onosproject/yang/model/KeyLeaf.java
+++ b/model/src/main/java/org/onosproject/yang/model/KeyLeaf.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present Open Networking Laboratory
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
 /**
  * Represents the List's key leaf value.
  */
-public class KeyLeaf {
+public class KeyLeaf implements Cloneable {
 
     private SchemaId leafSchema;
     private Object leafVal;
@@ -45,6 +45,19 @@
     }
 
     /**
+     * Creates and returns a deep copy of this object.
+     *
+     * @return cloned copy
+     * @throws CloneNotSupportedException if the object's class does not
+     *                                    support the {@code Cloneable} interface
+     */
+    public KeyLeaf clone() throws CloneNotSupportedException {
+        KeyLeaf clonedLeaf = (KeyLeaf) super.clone();
+        clonedLeaf.leafSchema = leafSchema.clone();
+        return clonedLeaf;
+    }
+
+    /**
      * Returns the node schema schemaId.
      *
      * @return node schema schemaId
diff --git a/model/src/main/java/org/onosproject/yang/model/LeafListKey.java b/model/src/main/java/org/onosproject/yang/model/LeafListKey.java
index 591dcb6..b7d082c 100644
--- a/model/src/main/java/org/onosproject/yang/model/LeafListKey.java
+++ b/model/src/main/java/org/onosproject/yang/model/LeafListKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present Open Networking Laboratory
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -56,6 +56,17 @@
         return val.toString();
     }
 
+    /**
+     * Creates and returns a deep copy of this object.
+     *
+     * @return cloned copy
+     * @throws CloneNotSupportedException if the object's class does not
+     *                                    support the {@code Cloneable} interface
+     */
+    public LeafListKey clone() throws CloneNotSupportedException {
+        return (LeafListKey) super.clone();
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(schemaId, val);
diff --git a/model/src/main/java/org/onosproject/yang/model/ListKey.java b/model/src/main/java/org/onosproject/yang/model/ListKey.java
index ebc9057..4082cc5 100644
--- a/model/src/main/java/org/onosproject/yang/model/ListKey.java
+++ b/model/src/main/java/org/onosproject/yang/model/ListKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present Open Networking Laboratory
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package org.onosproject.yang.model;
 
 import java.util.LinkedList;
@@ -52,6 +51,23 @@
         return keyLeafs;
     }
 
+    /**
+     * Creates and returns a deep copy of this object.
+     *
+     * @return cloned copy
+     * @throws CloneNotSupportedException if the object's class does not
+     *                                    support the {@code Cloneable} interface
+     */
+    public ListKey clone() throws CloneNotSupportedException {
+        ListKey clonedListKey = (ListKey) super.clone();
+        List<KeyLeaf> clonedKeyLeafs = new LinkedList<>();
+        for (KeyLeaf leaf : keyLeafs) {
+            clonedKeyLeafs.add(leaf.clone());
+        }
+        clonedListKey.keyLeafs = clonedKeyLeafs;
+        return clonedListKey;
+    }
+
     public int compareTo(ListKey o) {
         //TODO: implement me
         return 0;
diff --git a/model/src/main/java/org/onosproject/yang/model/NodeKey.java b/model/src/main/java/org/onosproject/yang/model/NodeKey.java
index 21dc12f..5149072 100644
--- a/model/src/main/java/org/onosproject/yang/model/NodeKey.java
+++ b/model/src/main/java/org/onosproject/yang/model/NodeKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present Open Networking Laboratory
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package org.onosproject.yang.model;
 
 import java.util.Objects;
@@ -28,7 +27,7 @@
  * Abstraction of an entity which identifies a node uniquely among its
  * siblings.
  */
-public class NodeKey<E extends NodeKey> implements Comparable<E> {
+public class NodeKey<E extends NodeKey> implements Comparable<E>, Cloneable {
 
     protected SchemaId schemaId;
 
@@ -42,6 +41,15 @@
     }
 
     /**
+     * Returns node key builder.
+     *
+     * @return node key builder
+     */
+    public static NodeKeyBuilder builder() {
+        return new NodeKeyBuilder();
+    }
+
+    /**
      * Returns the schema identifier as minimal key required to identify a
      * branching node.
      *
@@ -57,15 +65,6 @@
         return schemaId.compareTo(o.schemaId());
     }
 
-    /**
-     * Returns node key builder.
-     *
-     * @return node key builder
-     */
-    public static NodeKeyBuilder builder() {
-        return new NodeKeyBuilder();
-    }
-
     @Override
     public int hashCode() {
         return hash(schemaId);
@@ -93,6 +92,19 @@
     }
 
     /**
+     * Creates and returns a deep copy of this object.
+     *
+     * @return cloned copy
+     * @throws CloneNotSupportedException if the object's class does not
+     *                                    support the {@code Cloneable} interface
+     */
+    public NodeKey clone() throws CloneNotSupportedException {
+        NodeKey clonedKey = (NodeKey) super.clone();
+        clonedKey.schemaId = schemaId.clone();
+        return clonedKey;
+    }
+
+    /**
      * Builder for node key.
      *
      * @param <B> node key type
diff --git a/model/src/main/java/org/onosproject/yang/model/ResourceId.java b/model/src/main/java/org/onosproject/yang/model/ResourceId.java
index ffedb13..98999ee 100644
--- a/model/src/main/java/org/onosproject/yang/model/ResourceId.java
+++ b/model/src/main/java/org/onosproject/yang/model/ResourceId.java
@@ -67,6 +67,17 @@
         return nodeKeyList;
     }
 
+    /**
+     * Returns resource identifier builder for a given resource identifier.
+     * It contains all the attributes from the resource identifier. It is to
+     * provide mutability of resource identifier using builder pattern.
+     *
+     * @return data node builder
+     */
+    public Builder copyBuilder() throws CloneNotSupportedException {
+        return new Builder(this);
+    }
+
     @Override
     public int hashCode() {
         return hash(nodeKeyList);
@@ -101,10 +112,57 @@
          */
         protected Object AppInfo;
 
-        private List<NodeKey> nodeKeyList = new LinkedList<>();
+        private List<NodeKey> nodeKeyList;
         private NodeKey.NodeKeyBuilder curKeyBuilder = null;
 
         /**
+         * Creates an instance of resource identifier builder.
+         */
+        public Builder() {
+            nodeKeyList = new LinkedList<>();
+        }
+
+        /**
+         * Creates an instance of resource identifier builder. This is used
+         * in scenario when builder is required from a given resource
+         * identifier.
+         *
+         * @param id old resource identifier
+         */
+        public Builder(ResourceId id) throws CloneNotSupportedException {
+            nodeKeyList = new LinkedList<>();
+            for (NodeKey key : id.nodeKeyList) {
+                nodeKeyList.add(key.clone());
+            }
+        }
+
+        /**
+         * Appends a given resource id to current builder.
+         *
+         * @param id resource identifier to be appended
+         * @return builder
+         */
+        public Builder append(ResourceId id) throws CloneNotSupportedException {
+            processCurKey();
+            curKeyBuilder = null;
+            Builder ob = id.copyBuilder();
+            nodeKeyList.addAll(ob.nodeKeyList);
+            return this;
+        }
+
+        /**
+         * Validates, build and add current key.
+         */
+        private void processCurKey() {
+            if (curKeyBuilder != null) {
+                if (curKeyBuilder instanceof LeafListKey.LeafListKeyBuilder) {
+                    throw new ModelException(LEAF_IS_TERMINAL);
+                }
+                nodeKeyList.add(curKeyBuilder.build());
+            }
+        }
+
+        /**
          * Adds the descendent node's schema identity.
          *
          * @param name      name of descendent node
@@ -112,16 +170,9 @@
          * @return updated builder pointing to the specified schema location
          */
         public Builder addBranchPointSchema(String name, String nameSpace) {
-            if (curKeyBuilder != null) {
-                if (curKeyBuilder instanceof LeafListKey.LeafListKeyBuilder) {
-                    throw new ModelException(LEAF_IS_TERMINAL);
-                }
-                nodeKeyList.add(curKeyBuilder.build());
-            }
-
+            processCurKey();
             curKeyBuilder = new NodeKey.NodeKeyBuilder();
             curKeyBuilder.schemaId(name, nameSpace);
-
             return this;
         }
 
diff --git a/model/src/main/java/org/onosproject/yang/model/SchemaId.java b/model/src/main/java/org/onosproject/yang/model/SchemaId.java
index 082c357..a257f79 100644
--- a/model/src/main/java/org/onosproject/yang/model/SchemaId.java
+++ b/model/src/main/java/org/onosproject/yang/model/SchemaId.java
@@ -26,7 +26,7 @@
  * Representation of an entity which identifies a schema node in the schema /
  * data tree.
  */
-public class SchemaId implements Comparable<SchemaId> {
+public class SchemaId implements Comparable<SchemaId>, Cloneable {
 
     private String name;
     private String nameSpace;
@@ -47,7 +47,7 @@
      *
      * @return node name
      */
-    String name() {
+    public String name() {
         return name;
     }
 
@@ -57,10 +57,21 @@
      *
      * @return node's namespace
      */
-    String namespace() {
+    public String namespace() {
         return nameSpace;
     }
 
+    /**
+     * Creates and returns a deep copy of this object.
+     *
+     * @return cloned copy
+     * @throws CloneNotSupportedException if the object's class does not
+     *                                    support the {@code Cloneable} interface
+     */
+    public SchemaId clone() throws CloneNotSupportedException {
+        return (SchemaId) super.clone();
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(name, nameSpace);