Change the APIs to instantiate Resource and ResourceId

Now, DiscreteResource/DiscreteResourceId is provided by DiscreteFactory.
Similarly, ContinuousResource/ContinuousResourceId is provided by
ContinuousFactory. These factory instances can be obtained by static
factory method such as Resource.discrete(...) or Resource.continuous(...).

Change-Id: Ic94f7336c0e1f74cf2dddcac899de300362aff3e
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 e3c5c47..749d87e 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,14 +16,16 @@
 package org.onosproject.net.newresource;
 
 import com.google.common.annotations.Beta;
-
+import com.google.common.collect.ImmutableList;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * An object that represent a resource in a network.
@@ -46,65 +48,6 @@
 
     DiscreteResource ROOT = new DiscreteResource();
 
-    static DiscreteResource discrete(DeviceId device) {
-        return new DiscreteResource(ResourceId.discrete(device));
-    }
-
-    /**
-     * Creates an resource path which represents a discrete-type resource from the specified components.
-     *
-     * @param device device ID which is the first component of the path
-     * @param components following components of the path. The order represents hierarchical structure of the resource.
-     * @return resource path instance
-     */
-    static DiscreteResource discrete(DeviceId device, Object... components) {
-        return new DiscreteResource(ResourceId.discrete(device, components));
-    }
-
-    /**
-     * Creates an resource path which represents a discrete-type resource from the specified components.
-     *
-     * @param device device ID which is the first component of the path
-     * @param port port number which is the second component of the path
-     * @param components following components of the path. The order represents hierarchical structure of the resource.
-     * @return resource path instance
-     */
-    static DiscreteResource discrete(DeviceId device, PortNumber port, Object... components) {
-        return new DiscreteResource(ResourceId.discrete(device, port, components));
-    }
-
-    /**
-     * Creates an resource path which represents a continuous-type resource from the specified components.
-     *
-     * @param value amount of the resource
-     * @param device device ID which is the first component of the path
-     * @param components following components of the path. The order represents hierarchical structure of the resource.
-     *                   The last element of this list must be an {@link Class} instance. Otherwise, this method throws
-     *                   an IllegalArgumentException.
-     * @return resource path instance
-     */
-    static ContinuousResource continuous(double value, DeviceId device, Object... components) {
-        checkArgument(components.length > 0,
-                "Length of components must be greater thant 0, but " + components.length);
-
-        return new ContinuousResource(ResourceId.continuous(device, components), value);
-    }
-
-    /**
-     * Creates an resource path which represents a continuous-type resource from the specified components.
-     *
-     * @param value amount of the resource
-     * @param device device ID which is the first component of the path.
-     * @param port port number which is the second component of the path.
-     * @param components following components of the path. The order represents hierarchical structure of the resource.
-     *                   The last element of this list must be an {@link Class} instance. Otherwise, this method throws
-     *                   an IllegalArgumentException.
-     * @return resource path instance
-     */
-    static ContinuousResource continuous(double value, DeviceId device, PortNumber port, Object... components) {
-        return new ContinuousResource(ResourceId.continuous(device, port, components), value);
-    }
-
     /**
      * Returns the components of this resource path.
      *
@@ -163,4 +106,189 @@
      * @return the ID of this resource path
      */
     ResourceId id();
+
+    /**
+     * Create a factory for discrete-type with the specified resource ID.
+     *
+     * @param id resource ID
+     * @return {@link DiscreteFactory}
+     */
+    static DiscreteFactory discrete(DiscreteResourceId id) {
+        checkNotNull(id);
+
+        return new DiscreteFactory(id);
+    }
+
+    /**
+     * Creates a factory for discrete-type with the specified parent ID and child.
+     *
+     * @param parent ID of the parent
+     * @param child child
+     * @return {@link DiscreteFactory}
+     */
+    static DiscreteFactory discrete(DiscreteResourceId parent, Object child) {
+        checkNotNull(parent);
+        checkNotNull(child);
+        checkArgument(!(child instanceof Class<?>));
+
+        return new DiscreteFactory(new DiscreteResourceId(ImmutableList.builder()
+                .addAll(parent.components())
+                .add(child)
+                .build()));
+    }
+
+    /**
+     * Create a factory for discrete-type with the specified device ID.
+     *
+     * @param device device ID
+     * @return {@link DiscreteFactory}
+     */
+    static DiscreteFactory discrete(DeviceId device) {
+        checkNotNull(device);
+
+        return new DiscreteFactory(new DiscreteResourceId(ImmutableList.of(device)));
+    }
+
+    /**
+     * Create a factory for discrete-type with the specified device ID and components.
+     *
+     * @param device device ID
+     * @param components resource ID components other than the device ID
+     * @return {@link DiscreteFactory}
+     */
+    static DiscreteFactory discrete(DeviceId device, Object... components) {
+        checkNotNull(device);
+        checkNotNull(components);
+
+        return new DiscreteFactory(new DiscreteResourceId(ImmutableList.builder()
+                .add(device)
+                .add(components)
+                .build()));
+    }
+
+    /**
+     * Create a factory for discrete-type with the specified device ID, port number and components.
+     *
+     * @param device device ID
+     * @param port port number
+     * @param components resource ID components other than the device ID and port number
+     * @return {@link DiscreteFactory}
+     */
+    static DiscreteFactory discrete(DeviceId device, PortNumber port, Object... components) {
+        checkNotNull(device);
+        checkNotNull(port);
+        checkNotNull(components);
+
+        return new DiscreteFactory(new DiscreteResourceId(ImmutableList.builder()
+                .add(device)
+                .add(port)
+                .add(components)
+                .build()));
+    }
+
+    /**
+     * Create a factory for continuous-type with the specified resource ID.
+     *
+     * @param id resource ID
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(ContinuousResourceId id) {
+        checkNotNull(id);
+
+        return new ContinuousFactory(id);
+    }
+
+    /**
+     * Creates a factory for continuous-type wit the specified parent ID and child.
+     *
+     * @param parent ID of the parent
+     * @param child child
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(DiscreteResourceId parent, Class<?> child) {
+        checkNotNull(parent);
+        checkNotNull(child);
+
+        return new ContinuousFactory(new ContinuousResourceId(ImmutableList.builder()
+                .addAll(parent.components()), child));
+    }
+
+    /**
+     * Create a factory for continuous-type with the specified device ID and type.
+     *
+     * @param device device ID
+     * @param cls type of resource the returned factory will create
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(DeviceId device, Class<?> cls) {
+        checkNotNull(device);
+        checkNotNull(cls);
+
+        return new ContinuousFactory(new ContinuousResourceId(ImmutableList.builder().add(device), cls));
+    }
+
+    /**
+     * Create a factory for continuous-type with the specified device ID and components.
+     * The last element of the components must be a {@link Class} instance. Otherwise,
+     * an {@link IllegalArgumentException} is thrown.
+     *
+     * @param device device ID
+     * @param components resource ID components other than the device ID.
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(DeviceId device, Object... components) {
+        checkNotNull(device);
+        checkNotNull(components);
+        checkArgument(components.length > 1);
+
+        Object last = components[components.length - 1];
+        checkArgument(last instanceof Class<?>);
+
+        return new ContinuousFactory(new ContinuousResourceId(ImmutableList.builder()
+                .add(device)
+                .add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last));
+    }
+
+    /**
+     * Create a factory for continuous-type with the specified device ID, port number and type.
+     *
+     * @param device device ID
+     * @param port port number
+     * @param cls type of resource the returned factory will create
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(DeviceId device, PortNumber port, Class<?> cls) {
+        checkNotNull(device);
+        checkNotNull(port);
+        checkNotNull(cls);
+
+        return new ContinuousFactory(new ContinuousResourceId(ImmutableList.builder()
+                .add(device)
+                .add(port), cls));
+    }
+
+    /**
+     * Create a factory for continuous-type with the specified device ID and components.
+     * The last element of the components must be a {@link Class} instance. Otherwise,
+     * an {@link IllegalArgumentException} is thrown.
+     *
+     * @param device device ID
+     * @param port port number
+     * @param components resource ID components other than the device ID and port number.
+     * @return {@link ContinuousFactory}
+     */
+    static ContinuousFactory continuous(DeviceId device, PortNumber port, Object... components) {
+        checkNotNull(device);
+        checkNotNull(port);
+        checkNotNull(components);
+        checkArgument(components.length > 1);
+
+        Object last = components[components.length - 1];
+        checkArgument(last instanceof Class<?>);
+
+        return new ContinuousFactory(new ContinuousResourceId(ImmutableList.builder()
+                .add(device)
+                .add(port)
+                .add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last));
+    }
 }