ONOS-7007 dealing with root relative path

- workarounds to deal with root relative ResourceId used by DynamicConfigEvent
- fix issue, where duplicate KeyLeaf was getting added

Change-Id: I957044f8da3d71e064663011c8bd8fceeb1cf44e
diff --git a/apps/config/src/main/java/org/onosproject/d/config/ResourceIds.java b/apps/config/src/main/java/org/onosproject/d/config/ResourceIds.java
index fc875a9..a08c04a 100644
--- a/apps/config/src/main/java/org/onosproject/d/config/ResourceIds.java
+++ b/apps/config/src/main/java/org/onosproject/d/config/ResourceIds.java
@@ -18,10 +18,14 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.slf4j.LoggerFactory.getLogger;
 
+import java.util.Iterator;
+import java.util.Objects;
+
 import org.onosproject.yang.model.DataNode;
 import org.onosproject.yang.model.KeyLeaf;
 import org.onosproject.yang.model.LeafListKey;
 import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.NodeKey;
 import org.onosproject.yang.model.ResourceId;
 import org.onosproject.yang.model.SchemaId;
 import org.slf4j.Logger;
@@ -37,6 +41,14 @@
     private static final Logger log = getLogger(ResourceIds.class);
 
     /**
+     * Absolute ResourceId pointing at root node.
+     */
+    public static final ResourceId ROOT_ID = ResourceId.builder()
+            .addBranchPointSchema(DeviceResourceIds.ROOT_NAME,
+                                  DeviceResourceIds.DCS_NAMESPACE)
+            .build();
+
+    /**
      * Builds the ResourceId of specified {@code node}.
      *
      * @param parent ResourceId of {@code node} parent
@@ -113,8 +125,20 @@
     public static ResourceId relativize(ResourceId base, ResourceId child) {
         checkArgument(child.nodeKeys().size() >= base.nodeKeys().size(),
                       "%s path must be deeper than base prefix %s", child, base);
-        checkArgument(base.nodeKeys().equals(child.nodeKeys().subList(0, base.nodeKeys().size())),
-                      "%s is not a prefix of %s", child, base);
+        @SuppressWarnings("rawtypes")
+        Iterator<NodeKey> bIt = base.nodeKeys().iterator();
+        @SuppressWarnings("rawtypes")
+        Iterator<NodeKey> cIt = child.nodeKeys().iterator();
+        while (bIt.hasNext()) {
+            NodeKey<?> b = bIt.next();
+            NodeKey<?> c = cIt.next();
+
+            checkArgument(Objects.equals(b, c),
+                          "%s is not a prefix of %s.\n" +
+                          "b:%s != c:%s",
+                          base, child,
+                          b, c);
+        }
 
         return ResourceId.builder().append(child.nodeKeys().subList(base.nodeKeys().size(),
                                                                     child.nodeKeys().size())).build();
@@ -133,4 +157,9 @@
                prefix.nodeKeys().equals(child.nodeKeys().subList(0, prefix.nodeKeys().size()));
     }
 
+    public static boolean startsWithRootNode(ResourceId path) {
+        return !path.nodeKeys().isEmpty() &&
+                DeviceResourceIds.ROOT_NAME.equals(path.nodeKeys().get(0).schemaId().name());
+    }
+
 }