Use concrete types instead of abstract types

- ResourceId -> DiscreteResourceId/ContinuousResourceId
- Resource -> DiscreteResource/ContinuousResource

In addition, stop sharing the implementations in the super classes

Change-Id: I44662f6b7c23a23c30844a5b693e1cabab2cc091
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResource.java b/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResource.java
index b0573dc..a15ed34 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResource.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResource.java
@@ -16,8 +16,11 @@
 package org.onosproject.net.newresource;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
 
+import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 
 /**
  * Represents a resource path which specifies a resource which can be measured
@@ -27,15 +30,20 @@
  * implementation only. It is not for resource API user.
  */
 @Beta
-// TODO: consider how to restrict the visibility
-public final class ContinuousResource extends Resource {
+public final class ContinuousResource implements Resource {
+    private final ContinuousResourceId id;
     private final double value;
 
-    ContinuousResource(ResourceId id, double value) {
-        super(id);
+    ContinuousResource(ContinuousResourceId id, double value) {
+        this.id = id;
         this.value = value;
     }
 
+    @Override
+    public ContinuousResourceId id() {
+        return id;
+    }
+
     /**
      * The user of this methods must receive the return value as Double or double.
      * Otherwise, this methods throws an exception.
@@ -49,6 +57,44 @@
         return (T) Double.valueOf(value);
     }
 
+    /**
+     * Returns the value of the resource amount.
+     *
+     * @return the value of the resource amount
+     */
+    // FIXME: overlapping a purpose with volume()
+    public double value() {
+        return value;
+    }
+
+    @Override
+    public List<Object> components() {
+        return id.components;
+    }
+
+    @Override
+    public Object last() {
+        if (id.components.isEmpty()) {
+            return null;
+        }
+        return id.components.get(id.components.size() - 1);
+    }
+
+    @Override
+    public DiscreteResource child(Object child) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ContinuousResource child(Class<?> child, double value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Optional<DiscreteResource> parent() {
+        return Optional.ofNullable(id.parent()).map(DiscreteResource::new);
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(id(), value);
@@ -67,13 +113,11 @@
                 && Objects.equals(this.value, other.value);
     }
 
-    /**
-     * Returns the value of the resource amount.
-     *
-     * @return the value of the resource amount
-     */
-    // FIXME: overlapping a purpose with volume()
-    public double value() {
-        return value;
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("id", id)
+                .add("volume", value)
+                .toString();
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResourceId.java b/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResourceId.java
index cd25a92..b0937bc 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResourceId.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/ContinuousResourceId.java
@@ -18,6 +18,8 @@
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
 
+import java.util.Objects;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
@@ -27,16 +29,73 @@
  * implementation only. It is not for resource API user.
  */
 @Beta
-// TODO: consider how to restrict the visibility
 public final class ContinuousResourceId extends ResourceId {
+    final ImmutableList<Object> components;
+
     // for printing purpose only (used in toString() implementation)
     private final String name;
 
     ContinuousResourceId(ImmutableList<Object> components, String name) {
-        super(components);
+        this.components = components;
         this.name = checkNotNull(name);
     }
 
+    ContinuousResourceId(ImmutableList.Builder<Object> parentComponents, Class<?> last) {
+        this.components = parentComponents.add(last.getCanonicalName()).build();
+        this.name = last.getSimpleName();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * A child of a continuous-type resource is prohibited.
+     * {@link UnsupportedOperationException} is always thrown.
+     */
+    @Override
+    public DiscreteResourceId child(Object child) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * A child of a continuous-type resource is prohibited.
+     * {@link UnsupportedOperationException} is always thrown.
+     */
+    @Override
+    public ContinuousResourceId child(Class<?> child) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    DiscreteResourceId parent() {
+        if (components.size() == 0) {
+            return null;
+        }
+        if (components.size() == 1) {
+            return ROOT;
+        } else {
+            return new DiscreteResourceId(components.subList(0, components.size() - 1));
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return components.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final ContinuousResourceId other = (ContinuousResourceId) obj;
+        return Objects.equals(this.components, other.components);
+    }
+
     @Override
     public String toString() {
         // due to performance consideration, the value might need to be stored in a field
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResource.java b/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResource.java
index 9efbbd1..9e9468a 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResource.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResource.java
@@ -16,8 +16,13 @@
 package org.onosproject.net.newresource;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
 
+import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * Represents a resource path which specifies a resource which can be measured
@@ -28,14 +33,20 @@
  * </p>
  */
 @Beta
-// TODO: consider how to restrict the visibility
-public final class DiscreteResource extends Resource {
-    protected DiscreteResource() {
-        super();
+public final class DiscreteResource implements Resource {
+    private final DiscreteResourceId id;
+
+    DiscreteResource(DiscreteResourceId id) {
+        this.id = id;
     }
 
-    DiscreteResource(ResourceId id) {
-        super(id);
+    protected DiscreteResource() {
+        this.id = ResourceId.ROOT;
+    }
+
+    @Override
+    public DiscreteResourceId id() {
+        return id;
     }
 
     /**
@@ -53,6 +64,36 @@
     }
 
     @Override
+    public List<Object> components() {
+        return id.components;
+    }
+
+    @Override
+    public Object last() {
+        if (id.components.isEmpty()) {
+            return null;
+        }
+        return id.components.get(id.components.size() - 1);
+    }
+
+    @Override
+    public DiscreteResource child(Object child) {
+        checkArgument(!(child instanceof Class<?>));
+
+        return new DiscreteResource(id().child(child));
+    }
+
+    @Override
+    public ContinuousResource child(Class<?> child, double value) {
+        return new ContinuousResource(id.child(child), value);
+    }
+
+    @Override
+    public Optional<DiscreteResource> parent() {
+        return Optional.ofNullable(id.parent()).map(DiscreteResource::new);
+    }
+
+    @Override
     public int hashCode() {
         // the value returing from volume() is excluded due to optimization
         return id().hashCode();
@@ -70,4 +111,12 @@
         // the value returing from volume() is excluded due to optimization
         return Objects.equals(this.id(), other.id());
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("id", id)
+                .add("volume", volume())
+                .toString();
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResourceId.java b/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResourceId.java
index cf9d334..035561d 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResourceId.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/DiscreteResourceId.java
@@ -18,6 +18,11 @@
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
 
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * ResourceId for {@link DiscreteResource}.
  *
@@ -25,13 +30,65 @@
  * implementation only. It is not for resource API user.
  */
 @Beta
-// TODO: consider how to restrict the visibility
 public final class DiscreteResourceId extends ResourceId {
+    final ImmutableList<Object> components;
+
     DiscreteResourceId(ImmutableList<Object> components) {
-        super(components);
+        this.components = components;
     }
 
     DiscreteResourceId() {
-        super();
+        this.components = ImmutableList.of();
+    }
+
+    @Override
+    public DiscreteResourceId child(Object child) {
+        checkArgument(!(child instanceof Class<?>));
+
+        return new DiscreteResourceId(ImmutableList.builder()
+                .addAll(components)
+                .add(child)
+                .build());
+    }
+
+    @Override
+    public ContinuousResourceId child(Class<?> child) {
+        checkNotNull(child);
+
+        return new ContinuousResourceId(ImmutableList.builder().addAll(components), child);
+    }
+
+    @Override
+    DiscreteResourceId parent() {
+        if (components.size() == 0) {
+            return null;
+        }
+        if (components.size() == 1) {
+            return ROOT;
+        } else {
+            return new DiscreteResourceId(components.subList(0, components.size() - 1));
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return components.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final DiscreteResourceId other = (DiscreteResourceId) obj;
+        return Objects.equals(this.components, other.components);
+    }
+
+    @Override
+    public String toString() {
+        return components.toString();
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/Resource.java b/core/api/src/main/java/org/onosproject/net/newresource/Resource.java
index 1dadcc2..a2b539e 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/Resource.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/Resource.java
@@ -16,7 +16,6 @@
 package org.onosproject.net.newresource;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.MoreObjects;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 
@@ -24,8 +23,6 @@
 import java.util.Optional;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 
 /**
  * An object that represent a resource in a network.
@@ -44,14 +41,11 @@
  * VLAN ID:100/Device:1/Port:1 is not valid because a link is not a sub-component of a VLAN ID.
  */
 @Beta
-public abstract class Resource {
+public interface Resource {
 
-    private final DiscreteResource parent;
-    private final ResourceId id;
+    DiscreteResource ROOT = new DiscreteResource();
 
-    public static final DiscreteResource ROOT = new DiscreteResource();
-
-    public static Resource discrete(DeviceId device) {
+    static DiscreteResource discrete(DeviceId device) {
         return new DiscreteResource(ResourceId.discrete(device));
     }
 
@@ -62,7 +56,7 @@
      * @param components following components of the path. The order represents hierarchical structure of the resource.
      * @return resource path instance
      */
-    public static Resource discrete(DeviceId device, Object... components) {
+    static DiscreteResource discrete(DeviceId device, Object... components) {
         return new DiscreteResource(ResourceId.discrete(device, components));
     }
 
@@ -74,7 +68,7 @@
      * @param components following components of the path. The order represents hierarchical structure of the resource.
      * @return resource path instance
      */
-    public static Resource discrete(DeviceId device, PortNumber port, Object... components) {
+    static DiscreteResource discrete(DeviceId device, PortNumber port, Object... components) {
         return new DiscreteResource(ResourceId.discrete(device, port, components));
     }
 
@@ -88,7 +82,7 @@
      *                   an IllegalArgumentException.
      * @return resource path instance
      */
-    public static Resource continuous(double value, DeviceId device, Object... components) {
+    static ContinuousResource continuous(double value, DeviceId device, Object... components) {
         checkArgument(components.length > 0,
                 "Length of components must be greater thant 0, but " + components.length);
 
@@ -106,40 +100,16 @@
      *                   an IllegalArgumentException.
      * @return resource path instance
      */
-    public static Resource continuous(double value, DeviceId device, PortNumber port, Object... components) {
+    static ContinuousResource continuous(double value, DeviceId device, PortNumber port, Object... components) {
         return new ContinuousResource(ResourceId.continuous(device, port, components), value);
     }
 
     /**
-     * Creates an resource path from the specified id.
-     *
-     * @param id id of the path
-     */
-    protected Resource(ResourceId id) {
-        checkNotNull(id);
-
-        this.id = id;
-        if (id.components.size() == 1) {
-            this.parent = ROOT;
-        } else {
-            this.parent = new DiscreteResource(id.parent());
-        }
-    }
-
-    // for serialization
-    protected Resource() {
-        this.parent = null;
-        this.id = ResourceId.ROOT;
-    }
-
-    /**
      * Returns the components of this resource path.
      *
      * @return the components of this resource path
      */
-    public List<Object> components() {
-        return id.components;
-    }
+    List<Object> components();
 
     /**
      * Returns the volume of this resource.
@@ -147,7 +117,7 @@
      * @return the volume of this resource
      */
     // TODO: think about other naming possibilities. amount? quantity?
-    public abstract <T> T volume();
+    <T> T volume();
 
     /**
      * Returns the parent resource path of this instance.
@@ -156,9 +126,7 @@
      * @return the parent resource path of this instance.
      * If there is no parent, empty instance will be returned.
      */
-    public Optional<DiscreteResource> parent() {
-        return Optional.ofNullable(parent);
-    }
+    Optional<DiscreteResource> parent();
 
     /**
      * Returns a child resource path of this instance with specifying the child object.
@@ -167,11 +135,7 @@
      * @param child child object
      * @return a child resource path
      */
-    public Resource child(Object child) {
-        checkState(this instanceof DiscreteResource);
-
-        return new DiscreteResource(id().child(child));
-    }
+    DiscreteResource child(Object child);
 
     /**
      * Returns a child resource path of this instance with specifying a child object and
@@ -181,11 +145,7 @@
      * @param value value
      * @return a child resource path
      */
-    public Resource child(Object child, double value) {
-        checkState(this instanceof DiscreteResource);
-
-        return new ContinuousResource(id.child(child), value);
-    }
+    ContinuousResource child(Class<?> child, double value);
 
     /**
      * Returns the last component of this instance.
@@ -193,28 +153,12 @@
      * @return the last component of this instance.
      * The return value is equal to the last object of {@code components()}.
      */
-    public Object last() {
-        if (id.components.isEmpty()) {
-            return null;
-        }
-        return id.components.get(id.components.size() - 1);
-    }
+    Object last();
 
     /**
      * Returns the ID of this resource path.
      *
      * @return the ID of this resource path
      */
-    public ResourceId id() {
-        return id;
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("id", id())
-                .add("volume", volume())
-                .toString();
-    }
-
+    ResourceId id();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/ResourceId.java b/core/api/src/main/java/org/onosproject/net/newresource/ResourceId.java
index 93c4472..7638f64 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/ResourceId.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/ResourceId.java
@@ -21,11 +21,8 @@
 import org.onosproject.net.PortNumber;
 
 import java.util.Arrays;
-import java.util.Objects;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 
 /**
  * Represents identifier of resource.
@@ -33,18 +30,16 @@
  */
 @Beta
 public abstract class ResourceId {
-    static final ResourceId ROOT = new DiscreteResourceId();
+    static final DiscreteResourceId ROOT = new DiscreteResourceId();
 
-    final ImmutableList<Object> components;
-
-    static ResourceId discrete(DeviceId device, Object... components) {
+    static DiscreteResourceId discrete(DeviceId device, Object... components) {
         return new DiscreteResourceId(ImmutableList.builder()
                 .add(device)
                 .add(components)
                 .build());
     }
 
-    static ResourceId discrete(DeviceId device, PortNumber port, Object... components) {
+    static DiscreteResourceId discrete(DeviceId device, PortNumber port, Object... components) {
         return new DiscreteResourceId(ImmutableList.builder()
                 .add(device)
                 .add(port)
@@ -52,92 +47,41 @@
                 .build());
     }
 
-    static ResourceId continuous(DeviceId device, Object... components) {
+    static ContinuousResourceId continuous(DeviceId device, Object... components) {
         Object last = components[components.length - 1];
         checkArgument(last instanceof Class<?>);
 
-        return continuous(ImmutableList.builder()
+        return new ContinuousResourceId(ImmutableList.builder()
                 .add(device)
                 .add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last);
     }
 
-    static ResourceId continuous(DeviceId device, PortNumber port, Object... components) {
+    static ContinuousResourceId continuous(DeviceId device, PortNumber port, Object... components) {
         Object last = components[components.length - 1];
         checkArgument(last instanceof Class<?>);
 
-        return continuous(ImmutableList.builder()
+        return new ContinuousResourceId(ImmutableList.builder()
                 .add(device)
                 .add(port)
                 .add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last);
     }
 
-    private static ResourceId continuous(ImmutableList.Builder<Object> parentComponents, Class<?> last) {
-        return new ContinuousResourceId(parentComponents
-                .add(last.getCanonicalName())
-                .build(), last.getSimpleName());
-    }
-
-    protected ResourceId(ImmutableList<Object> components) {
-        this.components = checkNotNull(components);
-    }
-
-    // for serializer
-    protected ResourceId() {
-        this.components = ImmutableList.of();
-    }
-
-    // IndexOutOfBoundsException is raised when the instance is equal to ROOT
-    ResourceId parent() {
-        if (components.size() == 1) {
-            return ROOT;
-        } else {
-            return new DiscreteResourceId(components.subList(0, components.size() - 1));
-        }
-    }
+    abstract DiscreteResourceId parent();
 
     /**
      * Returns a resource ID of a child of this resource based on the specified object.
-     * If the argument is an instance of {@link Class}, this method returns an instance of
-     * {@link ContinuousResourceId}. Otherwise, it returns an instance of {@link DiscreteResourceId}
-     * This method only work when the receiver is {@link DiscreteResourceId}. Otherwise,
-     * this method throws an exception.
+     * If the given object is a {@link Class} instance, {@link IllegalArgumentException} is thrown.
      *
      * @param child the last component of the child
      * @return a child resource ID
      */
-    public ResourceId child(Object child) {
-        checkState(this instanceof DiscreteResourceId);
+    public abstract DiscreteResourceId child(Object child);
 
-        if (child instanceof Class<?>) {
-            return continuous(ImmutableList.builder().addAll(components), (Class<?>) child);
-        } else {
-            return new DiscreteResourceId(ImmutableList.builder()
-                    .addAll(components)
-                    .add(child)
-                    .build());
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        return components.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        final ResourceId other = (ResourceId) obj;
-        return Objects.equals(this.components, other.components);
-    }
-
-    @Override
-    public String toString() {
-        return components.toString();
-    }
-
+    /**
+     * Returns a resource ID of a child of this resource based on the specified object.
+     *
+     * @param child the last component of the child
+     * @return a child resource ID
+     */
+    public abstract ContinuousResourceId child(Class<?> child);
 }
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 7862dfc..b92db06 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -181,8 +181,6 @@
 import org.onosproject.net.newresource.DiscreteResource;
 import org.onosproject.net.newresource.DiscreteResourceId;
 import org.onosproject.net.newresource.ResourceAllocation;
-import org.onosproject.net.newresource.ResourceId;
-import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.packet.DefaultOutboundPacket;
 import org.onosproject.net.packet.DefaultPacketRequest;
 import org.onosproject.net.packet.PacketPriority;
@@ -442,10 +440,8 @@
                     DefaultLinkResourceAllocations.class,
                     BandwidthResourceAllocation.class,
                     LambdaResourceAllocation.class,
-                    Resource.class,
                     DiscreteResource.class,
                     ContinuousResource.class,
-                    ResourceId.class,
                     DiscreteResourceId.class,
                     ContinuousResourceId.class,
                     ResourceAllocation.class,