Add NormalizedNode.contract()
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / YangInstanceIdentifier.java
index d02b7bc01e9a0a13baf3e2f680311e21994f568f..a7539e9167f08cb0917ba2b532e12f22e925194e 100644 (file)
@@ -12,6 +12,7 @@ import static com.google.common.base.Verify.verify;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.VerifyException;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -44,7 +45,6 @@ import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.util.HashCodeBuilder;
 import org.opendaylight.yangtools.util.ImmutableOffsetMap;
-import org.opendaylight.yangtools.util.SharedSingletonMap;
 import org.opendaylight.yangtools.util.SingletonSet;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
@@ -54,36 +54,29 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
  * Unique identifier of a particular node instance in the data tree.
  *
  * <p>
- * Java representation of YANG Built-in type <code>instance-identifier</code>,
- * which conceptually is XPath expression minimized to uniquely identify element
- * in data tree which conforms to constraints maintained by YANG Model,
+ * Java representation of YANG Built-in type {@code instance-identifier}, which conceptually is XPath expression
+ * minimized to uniquely identify element in data tree which conforms to constraints maintained by YANG Model,
  * effectively this makes Instance Identifier a path to element in data tree.
  *
  * <p>
- * Constraints put in YANG specification on instance-identifier allowed it to be
- * effectively represented in Java and it's evaluation does not require
- * full-blown XPath processor.
+ * Constraints put in YANG specification on instance-identifier allowed it to be effectively represented in Java and its
+ * evaluation does not require a full-blown XPath processor.
  *
- * <p>
- * <h3>Path Arguments</h3>
- * Path to the node represented in instance identifier consists of
- * {@link PathArgument} which carries necessary information to uniquely identify
- * node on particular level in the subtree.
+ * <h2>Path Arguments</h2>
+ * Path to the node represented in instance identifier consists of {@link PathArgument} which carries necessary
+ * information to uniquely identify node on particular level in the subtree.
  *
  * <ul>
- * <li>{@link NodeIdentifier} - Identifier of node, which has cardinality
- * <code>0..1</code> in particular subtree in data tree.</li>
- * <li>{@link NodeIdentifierWithPredicates} - Identifier of node (list item),
- * which has cardinality <code>0..n</code>.</li>
- * <li>{@link NodeWithValue} - Identifier of instance <code>leaf</code> node or
- * <code>leaf-list</code> node.</li>
- * <li>{@link AugmentationIdentifier} - Identifier of instance of
- * <code>augmentation</code> node.</li>
+ *   <li>{@link NodeIdentifier} - Identifier of node, which has cardinality {@code 0..1} in particular subtree in data
+ *       tree</li>
+ *   <li>{@link NodeIdentifierWithPredicates} - Identifier of node (list item), which has cardinality {@code 0..n}</li>
+ *   <li>{@link NodeWithValue} - Identifier of instance {@code leaf} node or {@code leaf-list} node</li>
+ *   <li>{@link AugmentationIdentifier} - Identifier of instance of {@code augmentation} node</li>
  * </ul>
  *
  * @see <a href="http://tools.ietf.org/html/rfc6020#section-9.13">RFC6020</a>
  */
-// FIXME: 5.0.0: this concept needs to be moved to yang-common, as parser components need the ability to refer
+// FIXME: 7.0.0: this concept needs to be moved to yang-common, as parser components need the ability to refer
 //               to data nodes -- most notably XPath expressions and {@code default} statement arguments need to be able
 //               to represent these.
 public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentifier>, Immutable, Serializable {
@@ -129,7 +122,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
      *
      * @return A optimized equivalent instance.
      */
-    @Beta
     public abstract @NonNull YangInstanceIdentifier toOptimized();
 
     /**
@@ -140,6 +132,15 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
      */
     public abstract @Nullable YangInstanceIdentifier getParent();
 
+    /**
+     * Return the conceptual parent {@link YangInstanceIdentifier}, which has one item less in
+     * {@link #getPathArguments()}.
+     *
+     * @return Parent {@link YangInstanceIdentifier}
+     * @throws VerifyException if this object is {@link #empty()}.
+     */
+    public abstract @NonNull YangInstanceIdentifier coerceParent();
+
     /**
      * Return the ancestor {@link YangInstanceIdentifier} with a particular depth, e.g. number of path arguments.
      *
@@ -185,6 +186,11 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
         return FixedYangInstanceIdentifier.create(path, hash.build());
     }
 
+    public static @NonNull YangInstanceIdentifier create(final PathArgument pathArgument) {
+        return new FixedYangInstanceIdentifier(ImmutableList.of(pathArgument),
+            HashCodeBuilder.nextHashCode(1, pathArgument));
+    }
+
     public static @NonNull YangInstanceIdentifier create(final PathArgument... path) {
         // We are forcing a copy, since we cannot trust the user
         return create(Arrays.asList(path));
@@ -491,7 +497,7 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
         }
 
         protected int hashCodeImpl() {
-            return 31 + getNodeType().hashCode();
+            return nodeType.hashCode();
         }
 
         @Override
@@ -733,12 +739,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
             return keyValues.size() == 1 ? of(keyValues, node) : new Regular(node, keyValues);
         }
 
-        @Deprecated
-        public static @NonNull NodeIdentifierWithPredicates of(final QName node,
-                final SharedSingletonMap<QName, Object> keyValues) {
-            return of(node, keyValues.getEntry());
-        }
-
         private static @NonNull NodeIdentifierWithPredicates of(final Map<QName, Object> keyValues, final QName node) {
             return of(node, keyValues.entrySet().iterator().next());
         }
@@ -748,7 +748,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          *
          * @return Predicate set.
          */
-        @Beta
         public abstract @NonNull Set<Entry<QName, Object>> entrySet();
 
         /**
@@ -756,7 +755,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          *
          * @return Predicate values.
          */
-        @Beta
         public abstract @NonNull Set<QName> keySet();
 
         /**
@@ -766,7 +764,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          * @return True if the predicate is present, false otherwise
          * @throws NullPointerException if {@code key} is null
          */
-        @Beta
         public abstract boolean containsKey(QName key);
 
         /**
@@ -774,7 +771,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          *
          * @return Predicate values.
          */
-        @Beta
         public abstract @NonNull Collection<Object> values();
 
         @Beta
@@ -792,22 +788,14 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          *
          * @return The number of predicates present.
          */
-        @Beta
         public abstract int size();
 
         /**
          * A Map-like view of this identifier's predicates. The view is expected to be stable and effectively-immutable.
          *
          * @return Map of predicates.
-         * @deprecated This method in a provisional one. It can be used in the code base, but users requiring it should
-         *             contact <a href="mailto:yangtools-dev@lists.opendaylight.org">yangtools-dev</a> for migration
-         *             guidelines. Callers are strongly encouraged to explore {@link #entrySet()}, {@link #size()},
-         *             {@link #values()} and {@link #keySet()} as an alternative.
          */
         @Beta
-        @Deprecated
-        // FIXME: 5.0.0: evaluate the real usefulness of this. The problem here is Map.hashCode() and Map.equals(),
-        //               which limits our options.
         public abstract @NonNull Map<QName, Object> asMap();
 
         @Override
@@ -852,23 +840,20 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
     public static final class NodeWithValue<T> extends AbstractPathArgument {
         private static final long serialVersionUID = -3637456085341738431L;
 
-        private final T value;
+        private final @NonNull T value;
 
         public NodeWithValue(final QName node, final T value) {
             super(node);
-            this.value = value;
+            this.value = requireNonNull(value);
         }
 
-        public T getValue() {
+        public @NonNull T getValue() {
             return value;
         }
 
         @Override
         protected int hashCodeImpl() {
-            final int prime = 31;
-            int result = super.hashCodeImpl();
-            result = prime * result + YangInstanceIdentifier.hashCode(value);
-            return result;
+            return 31 * super.hashCodeImpl() + YangInstanceIdentifier.hashCode(value);
         }
 
         @Override
@@ -1095,7 +1080,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          * @return this builder
          * @throws NullPointerException if any of the arguments is null
          */
-        @Beta
         @NonNull InstanceIdentifierBuilder append(Collection<? extends PathArgument> args);
 
         /**
@@ -1105,7 +1089,6 @@ public abstract class YangInstanceIdentifier implements Path<YangInstanceIdentif
          * @return this builder
          * @throws NullPointerException if any of the arguments is null
          */
-        @Beta
         default @NonNull InstanceIdentifierBuilder append(final PathArgument... args) {
             return append(Arrays.asList(args));
         }