NormalizedNodeAggregator should also report empty
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / persisted / DatastoreSnapshot.java
index 3c5e86b21d6abfb49bcbd7d331de73aeba9ded8d..6330e5d4c257343a135f62b6e9ac3a8dcd429923 100644 (file)
@@ -7,13 +7,19 @@
  */
 package org.opendaylight.controller.cluster.datastore.persisted;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.ImmutableList;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.controller.cluster.raft.persisted.Snapshot;
 
 /**
  * Stores a snapshot of the internal state of a data store.
@@ -23,60 +29,132 @@ import javax.annotation.Nullable;
 public class DatastoreSnapshot implements Serializable {
     private static final long serialVersionUID = 1L;
 
+    private static final class Proxy implements Externalizable {
+        private static final long serialVersionUID = 1L;
+
+        private DatastoreSnapshot datastoreSnapshot;
+
+        // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
+        // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
+        @SuppressWarnings("checkstyle:RedundantModifier")
+        public Proxy() {
+            // For Externalizable
+        }
+
+        Proxy(final DatastoreSnapshot datastoreSnapshot) {
+            this.datastoreSnapshot = datastoreSnapshot;
+        }
+
+        @Override
+        public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject(datastoreSnapshot.type);
+            out.writeObject(datastoreSnapshot.shardManagerSnapshot);
+
+            out.writeInt(datastoreSnapshot.shardSnapshots.size());
+            for (ShardSnapshot shardSnapshot: datastoreSnapshot.shardSnapshots) {
+                out.writeObject(shardSnapshot);
+            }
+        }
+
+        @Override
+        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            String localType = (String)in.readObject();
+            ShardManagerSnapshot localShardManagerSnapshot = (ShardManagerSnapshot) in.readObject();
+
+            int size = in.readInt();
+            List<ShardSnapshot> localShardSnapshots = new ArrayList<>(size);
+            for (int i = 0; i < size; i++) {
+                localShardSnapshots.add((ShardSnapshot) in.readObject());
+            }
+
+            datastoreSnapshot = new DatastoreSnapshot(localType, localShardManagerSnapshot, localShardSnapshots);
+        }
+
+        private Object readResolve() {
+            return datastoreSnapshot;
+        }
+    }
+
     private final String type;
-    private final byte[] shardManagerSnapshot;
+    private final ShardManagerSnapshot shardManagerSnapshot;
     private final List<ShardSnapshot> shardSnapshots;
 
-    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Stores a reference to an externally mutable byte[] "
-            + "object but this is OK since this class is merely a DTO and does not process byte[] internally. "
-            + "Also it would be inefficient to create a return copy as the byte[] could be large.")
-    public DatastoreSnapshot(@Nonnull String type, @Nullable byte[] shardManagerSnapshot,
-            @Nonnull List<ShardSnapshot> shardSnapshots) {
-        this.type = Preconditions.checkNotNull(type);
+    public DatastoreSnapshot(@NonNull String type, @Nullable ShardManagerSnapshot shardManagerSnapshot,
+            @NonNull List<ShardSnapshot> shardSnapshots) {
+        this.type = requireNonNull(type);
         this.shardManagerSnapshot = shardManagerSnapshot;
-        this.shardSnapshots = ImmutableList.copyOf(Preconditions.checkNotNull(shardSnapshots));
+        this.shardSnapshots = ImmutableList.copyOf(shardSnapshots);
     }
 
-    @Nonnull
-    public String getType() {
+    public @NonNull String getType() {
         return type;
     }
 
-    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Exposes a mutable object stored in a field but "
-            + "this is OK since this class is merely a DTO and does not process byte[] internally. "
-            + "Also it would be inefficient to create a return copy as the byte[] could be large.")
-    @Nullable
-    public byte[] getShardManagerSnapshot() {
+    public @Nullable ShardManagerSnapshot getShardManagerSnapshot() {
         return shardManagerSnapshot;
     }
 
-    @Nonnull
-    public List<ShardSnapshot> getShardSnapshots() {
+    public @NonNull List<ShardSnapshot> getShardSnapshots() {
         return shardSnapshots;
     }
 
+    private Object writeReplace() {
+        return new Proxy(this);
+    }
+
     public static class ShardSnapshot implements Serializable {
         private static final long serialVersionUID = 1L;
 
+        private static final class Proxy implements Externalizable {
+            private static final long serialVersionUID = 1L;
+
+            private ShardSnapshot shardSnapshot;
+
+            // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
+            // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
+            @SuppressWarnings("checkstyle:RedundantModifier")
+            public Proxy() {
+                // For Externalizable
+            }
+
+            Proxy(final ShardSnapshot shardSnapshot) {
+                this.shardSnapshot = shardSnapshot;
+            }
+
+            @Override
+            public void writeExternal(ObjectOutput out) throws IOException {
+                out.writeObject(shardSnapshot.name);
+                out.writeObject(shardSnapshot.snapshot);
+            }
+
+            @Override
+            public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+                shardSnapshot = new ShardSnapshot((String)in.readObject(), (Snapshot) in.readObject());
+            }
+
+            private Object readResolve() {
+                return shardSnapshot;
+            }
+        }
+
         private final String name;
-        private final byte[] snapshot;
+        private final Snapshot snapshot;
 
-        public ShardSnapshot(@Nonnull String name, @Nonnull byte[] snapshot) {
-            this.name = Preconditions.checkNotNull(name);
-            this.snapshot = Preconditions.checkNotNull(snapshot);
+        public ShardSnapshot(@NonNull String name, @NonNull Snapshot snapshot) {
+            this.name = requireNonNull(name);
+            this.snapshot = requireNonNull(snapshot);
         }
 
-        @Nonnull
-        public String getName() {
+        public @NonNull String getName() {
             return name;
         }
 
-        @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Exposes a mutable object stored in a field but "
-                + "this is OK since this class is merely a DTO and does not process byte[] internally. "
-                + "Also it would be inefficient to create a return copy as the byte[] could be large.")
-        @Nonnull
-        public byte[] getSnapshot() {
+        public @NonNull Snapshot getSnapshot() {
             return snapshot;
         }
+
+        private Object writeReplace() {
+            return new Proxy(this);
+        }
     }
 }