Merge "Do not return null when no RPC is registered"
[yangtools.git] / yang / yang-binding / src / main / java / org / opendaylight / yangtools / yang / binding / InstanceIdentifier.java
index 4bf91e32ea9ed4c7e802c4007cae9bcfbb163ac5..09f0dc13c35cfcbe40f5729f67d06ffc71d352ea 100644 (file)
@@ -15,6 +15,9 @@ import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
 /**
  * Uniquely identifies data location in the overall of data tree 
  * modeled by YANG.
@@ -25,14 +28,14 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
 
     private final List<PathArgument> path;
     private final Class<T> targetType;
-    
+
     public InstanceIdentifier(Class<T> type) {
         path = Collections.<PathArgument> singletonList(new Item<>(type));
         this.targetType = type;
     }
 
     public InstanceIdentifier(List<PathArgument> path, Class<T> type) {
-        this.path = Collections.<PathArgument> unmodifiableList(new ArrayList<>(path));
+        this.path = ImmutableList.copyOf(path);
         this.targetType = type;
     }
 
@@ -41,6 +44,10 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
      * @return path
      */
     public List<PathArgument> getPath() {
+        return getPathArguments();
+    }
+    
+    public List<PathArgument> getPathArguments() {
         return this.path;
     }
 
@@ -53,6 +60,60 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         return "InstanceIdentifier [path=" + path + "]";
     }
 
+    /**
+     * Return an instance identifier trimmed at the first occurrence of a
+     * specific component type.
+     * 
+     * @param type component type
+     * @return trimmed instance identifier, or null if the component type
+     *         is not present.
+     */
+    public <T extends DataObject> InstanceIdentifier<T> firstIdentifierOf(final Class<T> type) {
+        int i = 1;
+        for (final PathArgument a : path) {
+            if (type.equals(a.getType())) {
+                return new InstanceIdentifier<>(path.subList(0, i), type);
+            }
+
+            ++i;
+        }
+
+        return null;
+    }
+
+    /**
+     * Return the key associated with the first component of specified type in
+     * an identifier.
+     * 
+     * @param listItem component type
+     * @param listKey component key type
+     * @return key associated with the component, or null if the component type
+     *         is not present.
+     */
+    public <N extends Identifiable<K> & DataObject, K extends Identifier<N>> K firstKeyOf(final Class<N> listItem, final Class<K> listKey) {
+        for (PathArgument i : path) {
+            if (listItem.equals(i.getType())) {
+                @SuppressWarnings("unchecked")
+                final K ret = ((IdentifiableItem<N, K>)i).getKey();
+                return ret;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return the key associated with the last component of the specified identifier.
+     * 
+     * @param id instance identifier
+     * @return key associated with the last component
+     */
+    public static <N extends Identifiable<K> & DataObject, K extends Identifier<N>> K keyOf(final InstanceIdentifier<N> id) {
+        @SuppressWarnings("unchecked")
+        final K ret = ((IdentifiableItem<N, K>)Iterables.getLast(id.getPath())).getKey();
+        return ret;
+    }
+
     /**
      * Path argument of {@link InstanceIdentifier}.
      * <p>
@@ -101,7 +162,7 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
                 return false;
             return true;
         }
-        
+
         @Override
         public String toString() {
             return type.getName();
@@ -159,25 +220,48 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
     }
 
     public interface InstanceIdentifierBuilder<T extends DataObject> extends Builder<InstanceIdentifier<T>> {
-
+        /**
+         * @deprecated use {@link child(Class)} or {@link augmentation(Class)} instead.
+         */
+        @Deprecated
         <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container);
 
+        /**
+         * @deprecated use {@link child(Class,Identifier)} or {@link augmentation(Class,Identifier)} instead.
+         */
+        @Deprecated
         <N extends Identifiable<K> & DataObject, K extends Identifier<N>> InstanceIdentifierBuilder<N> node(
                 Class<N> listItem, K listKey);
 
         <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container);
-        
+
         <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(
                 Class<N> listItem, K listKey);
 
+        <N extends DataObject & Augmentation<? super T>> InstanceIdentifierBuilder<N> augmentation(Class<N> container);
+        
+        InstanceIdentifier<T> build();
+
     }
 
+    /**
+     * @deprecated use {@link builder(Class)} or {@link builder(Class,Identifier)} instead.
+     */
+    @Deprecated
     @SuppressWarnings("rawtypes")
     public static InstanceIdentifierBuilder<?> builder() {
         return new BuilderImpl();
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <T extends ChildOf<? extends DataRoot>> InstanceIdentifierBuilder<T> builder(Class<T> container) {
+        return new BuilderImpl<T>().addNode(container);
+    }
+
+    public static <N extends Identifiable<K> & ChildOf<? extends DataRoot>, K extends Identifier<N>> InstanceIdentifierBuilder<N> builder(
+            Class<N> listItem, K listKey) {
+        return new BuilderImpl<N>().addNode(listItem, listKey);
+    }
+
     public static <T extends DataObject> InstanceIdentifierBuilder<T> builder(InstanceIdentifier<T> basePath) {
         return new BuilderImpl<T>(basePath.path,basePath.targetType);
     }
@@ -190,46 +274,65 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         public BuilderImpl() {
             this.path = new ArrayList<>();
         }
-        
 
         public BuilderImpl(List<? extends PathArgument> prefix,Class<? extends DataObject> target) {
             this.path = new ArrayList<>(prefix);
             this.target = target;
         }
 
+        @SuppressWarnings("unchecked")
+        private <N extends DataObject> InstanceIdentifierBuilder<N> addNode(Class<N> container) {
+            target = container;
+            path.add(new Item<N>(container));
+            return (InstanceIdentifierBuilder<N>) this;
+        }
+
+        @SuppressWarnings("unchecked")
+        private <N extends DataObject & Identifiable<K> , K extends Identifier<N>> InstanceIdentifierBuilder<N> addNode(
+                Class<N> listItem, K listKey) {
+            target = listItem;
+            path.add(new IdentifiableItem<N, K>(listItem, listKey));
+            return (InstanceIdentifierBuilder<N>) this;
+        }
+
         @SuppressWarnings({ "unchecked", "rawtypes" })
         @Override
         public InstanceIdentifier<T> toInstance() {
             List<PathArgument> immutablePath = Collections.unmodifiableList(new ArrayList<PathArgument>(path));
             return new InstanceIdentifier(immutablePath, target);
         }
+        
+        @Override
+        public InstanceIdentifier<T> build() {
+            return toInstance();
+        }
 
         @Override
-        @SuppressWarnings("unchecked")
         public <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container) {
-            target = container;
-            path.add(new Item<N>(container));
-            return (InstanceIdentifierBuilder<N>) this;
+            return addNode(container);
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public <N extends DataObject & Identifiable<K> , K extends Identifier<N>> InstanceIdentifierBuilder<N> node(
                 Class<N> listItem, K listKey) {
-            target = listItem;
-            path.add(new IdentifiableItem<N, K>(listItem, listKey));
-            return (InstanceIdentifierBuilder<N>) this;
+            return addNode(listItem, listKey);
         }
-        
+
         @Override
         public <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container) {
-            return node(container);
+            return addNode(container);
         }
-        
+
         @Override
         public <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(
                 Class<N> listItem, K listKey) {
-            return node(listItem,listKey);
+            return addNode(listItem,listKey);
+        }
+
+        @Override
+        public <N extends DataObject & Augmentation<? super T>> InstanceIdentifierBuilder<N> augmentation(
+                Class<N> container) {
+            return addNode(container);
         }
     }
 
@@ -278,7 +381,36 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
                 return false;
             }
         }
-        
         return true;
     }
+    
+    public boolean containsWildcarded(final InstanceIdentifier<?> other) {
+        if(other == null) {
+            throw new IllegalArgumentException("other should not be null");
+        }
+        final int localSize = this.path.size();
+        final List<PathArgument> otherPath = other.getPath();
+        if(localSize > other.path.size()) {
+            return false;
+        }
+        for(int i = 0;i<localSize;i++ ) {
+            final PathArgument localArgument = path.get(i);
+            if(!localArgument.getType().equals(otherPath.get(i).getType())) {
+                return false;
+            } 
+            if(localArgument instanceof IdentifiableItem<?, ?> && !localArgument.equals(otherPath.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean isWildcarded() {
+        for(PathArgument pathArgument : path) {
+            if(Identifiable.class.isAssignableFrom(pathArgument.getType()) && !(pathArgument instanceof IdentifiableItem<?, ?>)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }