Merge "Bug 3016 : This manual serialization of ImmutableList was done because in...
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / YangInstanceIdentifier.java
index 3423110bdc0e844996d90955a5c982f08ecba4a2..4488ac32c27d937fc6bc92f19d687ab782289b4e 100644 (file)
@@ -16,11 +16,13 @@ import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -70,19 +72,23 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
  * @see <a href="http://tools.ietf.org/html/rfc6020#section-9.13">RFC6020</a>
  */
 public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier>, Immutable, Serializable {
+    /**
+     * An empty {@link YangInstanceIdentifier}. It corresponds to the path of the conceptual
+     * root of the YANG namespace.
+     */
+    public static final YangInstanceIdentifier EMPTY = trustedCreate(Collections.<PathArgument>emptyList());
     @SuppressWarnings("rawtypes")
     private static final AtomicReferenceFieldUpdater<YangInstanceIdentifier, ImmutableList> LEGACYPATH_UPDATER =
             AtomicReferenceFieldUpdater.newUpdater(YangInstanceIdentifier.class, ImmutableList.class, "legacyPath");
     private static final AtomicReferenceFieldUpdater<YangInstanceIdentifier, String> TOSTRINGCACHE_UPDATER =
             AtomicReferenceFieldUpdater.newUpdater(YangInstanceIdentifier.class, String.class, "toStringCache");
-    private static final YangInstanceIdentifier EMPTY = trustedCreate(Collections.<PathArgument>emptyList());
     private static final Field PATHARGUMENTS_FIELD;
 
     private static final long serialVersionUID = 3L;
-    private transient final Iterable<PathArgument> pathArguments;
+    private final transient Iterable<PathArgument> pathArguments;
     private final int hash;
 
-    private volatile ImmutableList<PathArgument> legacyPath = null;
+    private transient volatile ImmutableList<PathArgument> legacyPath = null;
     private transient volatile String toStringCache = null;
 
     static {
@@ -97,7 +103,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         PATHARGUMENTS_FIELD = f;
     }
 
-    private final ImmutableList<PathArgument> getLegacyPath() {
+    private ImmutableList<PathArgument> getLegacyPath() {
         // Temporary variable saves a volatile read
         ImmutableList<PathArgument> ret = legacyPath;
         if (ret == null) {
@@ -155,16 +161,16 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         this.hash = hash;
     }
 
-    private static final YangInstanceIdentifier trustedCreate(final Iterable<PathArgument> path) {
+    private static YangInstanceIdentifier trustedCreate(final Iterable<PathArgument> path) {
         final HashCodeBuilder<PathArgument> hash = new HashCodeBuilder<>();
         for (PathArgument a : path) {
             hash.addArgument(a);
         }
 
-        return new YangInstanceIdentifier(path, hash.toInstance());
+        return new YangInstanceIdentifier(path, hash.build());
     }
 
-    public static final YangInstanceIdentifier create(final Iterable<? extends PathArgument> path) {
+    public static YangInstanceIdentifier create(final Iterable<? extends PathArgument> path) {
         if (Iterables.isEmpty(path)) {
             return EMPTY;
         }
@@ -172,7 +178,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         return trustedCreate(ImmutableList.copyOf(path));
     }
 
-    public static final YangInstanceIdentifier create(final PathArgument... path) {
+    public static YangInstanceIdentifier create(final PathArgument... path) {
         // We are forcing a copy, since we cannot trust the user
         return create(Arrays.asList(path));
     }
@@ -301,7 +307,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
      *
      * @return new builder for InstanceIdentifier with empty path arguments.
      */
-    static public InstanceIdentifierBuilder builder() {
+    public static InstanceIdentifierBuilder builder() {
         return new BuilderImpl();
     }
 
@@ -312,23 +318,10 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
      * @param origin Instace Identifier from which path arguments are copied.
      * @return new builder for InstanceIdentifier with path arguments copied from original instance identifier.
      */
-    static public InstanceIdentifierBuilder builder(final YangInstanceIdentifier origin) {
+    public static InstanceIdentifierBuilder builder(final YangInstanceIdentifier origin) {
         return new BuilderImpl(origin.getPathArguments(), origin.hashCode());
     }
 
-    /**
-     * Returns new builder for InstanceIdentifier with first path argument set to {@link NodeIdentifier}.
-     *
-     * @param node QName of first {@link NodeIdentifier} path argument.
-     * @return  new builder for InstanceIdentifier with first path argument set to {@link NodeIdentifier}.
-     *
-     * @deprecated Either use {@link #node(QName)} or instantiate an intermediate builder.
-     */
-    @Deprecated
-    public static InstanceIdentifierBuilder builder(final QName node) {
-        return builder().node(node);
-    }
-
     /**
      * Path argument / component of InstanceIdentifier
      *
@@ -440,11 +433,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
     }
 
     /**
-     *
      * Fluent Builder of Instance Identifier instances
-     *
-     * @
-     *
      */
     public interface InstanceIdentifierBuilder extends Builder<YangInstanceIdentifier> {
         /**
@@ -480,7 +469,14 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
          *
          * @return {@link YangInstanceIdentifier}
          */
+        @Override
         YangInstanceIdentifier build();
+
+        /*
+         * @deprecated use #build()
+         */
+        @Deprecated
+        YangInstanceIdentifier toInstance();
     }
 
     /**
@@ -644,16 +640,6 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
             this.childNames = ImmutableSet.copyOf(childNames);
         }
 
-        /**
-         * Augmentation node has no QName
-         *
-         * @deprecated Use {@link #AugmentationIdentifier(Set)} instead.
-         */
-        @Deprecated
-        public AugmentationIdentifier(final QName nodeType, final Set<QName> childNames) {
-            this(childNames);
-        }
-
         /**
          * Returns set of all possible child nodes
          *
@@ -665,7 +651,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
 
         @Override
         public String toString() {
-            final StringBuffer sb = new StringBuffer("AugmentationIdentifier{");
+            final StringBuilder sb = new StringBuilder("AugmentationIdentifier{");
             sb.append("childNames=").append(childNames).append('}');
             return sb.toString();
         }
@@ -765,7 +751,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
 
         @Override
         public YangInstanceIdentifier build() {
-            return new YangInstanceIdentifier(ImmutableList.copyOf(path), hash.toInstance());
+            return new YangInstanceIdentifier(ImmutableList.copyOf(path), hash.build());
         }
     }
 
@@ -820,6 +806,7 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
 
     private void readObject(final ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
         inputStream.defaultReadObject();
+        legacyPath = ImmutableList.copyOf((Collection<PathArgument>)inputStream.readObject());
 
         try {
             PATHARGUMENTS_FIELD.set(this, legacyPath);
@@ -828,6 +815,10 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
         }
     }
 
+    private Object readResolve() throws ObjectStreamException {
+        return legacyPath.isEmpty() ? EMPTY : this;
+    }
+
     private void writeObject(final ObjectOutputStream outputStream) throws IOException {
         /*
          * This may look strange, but what we are doing here is side-stepping the fact
@@ -836,7 +827,8 @@ public final class YangInstanceIdentifier implements Path<YangInstanceIdentifier
          * it out. The read path does the opposite -- it reads the legacyPath and then
          * uses invocation API to set the field.
          */
-        getLegacyPath();
+        ImmutableList<PathArgument> pathArguments = getLegacyPath();
         outputStream.defaultWriteObject();
+        outputStream.writeObject(pathArguments);
     }
 }