Use ResourceId or DiscreteResourceId when specifying a resource

Change-Id: I4e29558ec649510c8d08bb5e5f8ed10c189252e5
diff --git a/cli/src/main/java/org/onosproject/cli/net/AllocationsCommand.java b/cli/src/main/java/org/onosproject/cli/net/AllocationsCommand.java
index 4a350a9..ccaebd4 100644
--- a/cli/src/main/java/org/onosproject/cli/net/AllocationsCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/AllocationsCommand.java
@@ -30,8 +30,8 @@
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.newresource.DiscreteResourceId;
 import org.onosproject.net.newresource.ResourceAllocation;
-import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.ResourceService;
 
 import com.google.common.base.Strings;
@@ -107,7 +107,7 @@
         // TODO: Current design cannot deal with sub-resources
         //        (e.g., TX/RX under Port)
 
-        Resource resource = Resources.discrete(did, num).resource();
+        DiscreteResourceId resource = Resources.discrete(did, num).id();
         if (lambda) {
             //print("Lambda resources:");
             Collection<ResourceAllocation> allocations
diff --git a/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java b/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
index 37faa0b..c9a2ad6 100644
--- a/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/ResourcesCommand.java
@@ -34,6 +34,7 @@
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.TributarySlot;
 import org.onosproject.net.newresource.ContinuousResource;
+import org.onosproject.net.newresource.DiscreteResource;
 import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.ResourceService;
 
@@ -101,7 +102,13 @@
 
     private void printResource(Resource resource, int level) {
         // TODO add an option to show only available resource
-        Set<Resource> children = resourceService.getRegisteredResources(resource);
+        // workaround to preserve the original behavior of ResourceService#getRegisteredResources
+        Set<Resource> children;
+        if (resource instanceof DiscreteResource) {
+            children = resourceService.getRegisteredResources(((DiscreteResource) resource).id());
+        } else {
+            children = Collections.emptySet();
+        }
 
         if (resource.equals(Resource.ROOT)) {
             print("ROOT");
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java b/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
index 6dcd7ef..1a2fa2c 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
@@ -129,24 +129,22 @@
     /**
      * Returns resource allocations of the specified resource.
      *
-     * @param resource resource to check the allocation
+     * @param id ID of the resource to check the allocation
      * @return list of allocation information.
      * If the resource is not allocated, the return value is an empty list.
      */
-    // TODO: need to change the argument type to ResourceId
-    List<ResourceAllocation> getResourceAllocations(Resource resource);
+    List<ResourceAllocation> getResourceAllocations(ResourceId id);
 
     /**
      * Returns allocated resources being as children of the specified parent and being the specified resource type.
      *
-     * @param parent parent resource
+     * @param parent parent resource ID
      * @param cls class to specify a type of resource
      * @param <T> type of the resource
      * @return non-empty collection of resource allocations if resources are allocated with the subject and type,
      * empty collection if no resource is allocated with the subject and type
      */
-    // TODO: might need to change the first argument type to ResourceId or ResourceId.Discrete
-    <T> Collection<ResourceAllocation> getResourceAllocations(Resource parent, Class<T> cls);
+    <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls);
 
     /**
      * Returns resources allocated to the specified consumer.
@@ -159,20 +157,18 @@
     /**
      * Returns resources that point available child resources under the specified resource.
      *
-     * @param parent parent resource
+     * @param parent parent resource ID
      * @return available resources under the specified resource
      */
-    // TODO: need to change the argument type to ResourceId or ResourceId.Discrete
-    Set<Resource> getAvailableResources(Resource parent);
+    Set<Resource> getAvailableResources(DiscreteResourceId parent);
 
     /**
      * Returns resources registered under the specified resource.
      *
-     * @param parent parent resource
+     * @param parent parent resource ID
      * @return registered resources under the specified resource
      */
-    // TODO: need to change the argument type to ResourceId or ResourceId.Discrete
-    Set<Resource> getRegisteredResources(Resource parent);
+    Set<Resource> getRegisteredResources(DiscreteResourceId parent);
 
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java b/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
index cca8ed0..0e3eee8 100644
--- a/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
+++ b/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
@@ -81,12 +81,11 @@
      * The return value is a list having only one element when the given resource is discrete type.
      * The return value may have multiple elements when the given resource is continuous type.
      *
-     * @param resource resource whose allocated consumer to be returned
+     * @param id ID of the resource whose allocated consumer to be returned
      * @return resource consumers who are allocated the resource.
      * Returns empty list if there is no such consumer.
      */
-    // TODO: need to change the argument type to ResourceId
-    List<ResourceConsumer> getConsumers(Resource resource);
+    List<ResourceAllocation> getResourceAllocations(ResourceId id);
 
     /**
      * Returns the availability of the specified resource.
@@ -107,22 +106,20 @@
     /**
      * Returns a set of the child resources of the specified parent.
      *
-     * @param parent parent of the resource to be returned
+     * @param parent ID of the parent of the resource to be returned
      * @return a set of the child resources of the specified resource
      */
-    // TODO: need to change the argument type to ResourceId or ResourceId.Discrete
-    Set<Resource> getChildResources(Resource parent);
+    Set<Resource> getChildResources(DiscreteResourceId parent);
 
     /**
      * Returns a collection of the resources which are children of the specified parent and
      * whose type is the specified class.
      *
-     * @param parent parent of the resources to be returned
+     * @param parent ID of the parent of the resources to be returned
      * @param cls class instance of the children
      * @param <T> type of the resource
      * @return a collection of the resources which belongs to the specified subject and
      * whose type is the specified class.
      */
-    // TODO: need to change the argument type to ResourceId or ResourceId.Discrete
-    <T> Collection<Resource> getAllocatedResources(Resource parent, Class<T> cls);
+    <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls);
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
index c8c7e8f..94b178e 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
@@ -157,7 +157,7 @@
     }
 
     private Set<MplsLabel> findMplsLabel(ConnectPoint cp) {
-        return resourceService.getAvailableResources(Resources.discrete(cp.deviceId(), cp.port()).resource()).stream()
+        return resourceService.getAvailableResources(Resources.discrete(cp.deviceId(), cp.port()).id()).stream()
                 .filter(x -> x.last() instanceof MplsLabel)
                 .map(x -> (MplsLabel) x.last())
                 .collect(Collectors.toSet());
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
index d2f92d5..b76ece8 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
@@ -313,8 +313,7 @@
         if (ochCP != null) {
             OchPort ochPort = (OchPort) deviceService.getPort(ochCP.deviceId(), ochCP.port());
             Optional<IntentId> intentId =
-                    resourceService.getResourceAllocations(
-                            Resources.discrete(ochCP.deviceId(), ochCP.port()).resource())
+                    resourceService.getResourceAllocations(Resources.discrete(ochCP.deviceId(), ochCP.port()).id())
                             .stream()
                             .map(ResourceAllocation::consumer)
                             .filter(x -> x instanceof IntentId)
@@ -335,8 +334,7 @@
             }
 
             Optional<IntentId> intentId =
-                    resourceService.getResourceAllocations(
-                            Resources.discrete(oduPort.deviceId(), port.number()).resource())
+                    resourceService.getResourceAllocations(Resources.discrete(oduPort.deviceId(), port.number()).id())
                             .stream()
                             .map(ResourceAllocation::consumer)
                             .filter(x -> x instanceof IntentId)
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
index 2f04cfd..5b741bc 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
@@ -214,8 +214,8 @@
     private Set<OchSignal> findCommonLambdasOverLinks(List<Link> links) {
         return links.stream()
                 .flatMap(x -> Stream.of(
-                        Resources.discrete(x.src().deviceId(), x.src().port()).resource(),
-                        Resources.discrete(x.dst().deviceId(), x.dst().port()).resource()
+                        Resources.discrete(x.src().deviceId(), x.src().port()).id(),
+                        Resources.discrete(x.dst().deviceId(), x.dst().port()).id()
                 ))
                 .map(resourceService::getAvailableResources)
                 .map(x -> Iterables.filter(x, r -> r.last() instanceof OchSignal))
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java
index 93e2d8c..7309a09 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java
@@ -285,7 +285,7 @@
     }
 
     private Set<VlanId> findVlanId(ConnectPoint cp) {
-        return resourceService.getAvailableResources(Resources.discrete(cp.deviceId(), cp.port()).resource()).stream()
+        return resourceService.getAvailableResources(Resources.discrete(cp.deviceId(), cp.port()).id()).stream()
                 .filter(x -> x.last() instanceof VlanId)
                 .map(x -> (VlanId) x.last())
                 .collect(Collectors.toSet());
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
index 517ee10..5fc9d55 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
@@ -25,10 +25,12 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.GuavaCollectors;
 import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.net.newresource.DiscreteResourceId;
 import org.onosproject.net.newresource.ResourceAdminService;
 import org.onosproject.net.newresource.ResourceAllocation;
 import org.onosproject.net.newresource.ResourceConsumer;
 import org.onosproject.net.newresource.ResourceEvent;
+import org.onosproject.net.newresource.ResourceId;
 import org.onosproject.net.newresource.ResourceListener;
 import org.onosproject.net.newresource.ResourceService;
 import org.onosproject.net.newresource.Resource;
@@ -115,25 +117,21 @@
     }
 
     @Override
-    public List<ResourceAllocation> getResourceAllocations(Resource resource) {
-        checkNotNull(resource);
+    public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+        checkNotNull(id);
 
-        List<ResourceConsumer> consumers = store.getConsumers(resource);
-        return consumers.stream()
-                .map(x -> new ResourceAllocation(resource, x))
-                .collect(GuavaCollectors.toImmutableList());
+        return store.getResourceAllocations(id);
     }
 
     @Override
-    public <T> Collection<ResourceAllocation> getResourceAllocations(Resource parent, Class<T> cls) {
+    public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
         checkNotNull(parent);
         checkNotNull(cls);
 
         // We access store twice in this method, then the store may be updated by others
         Collection<Resource> resources = store.getAllocatedResources(parent, cls);
         return resources.stream()
-                .flatMap(resource -> store.getConsumers(resource).stream()
-                        .map(consumer -> new ResourceAllocation(resource, consumer)))
+                .flatMap(resource -> store.getResourceAllocations(resource.id()).stream())
                 .collect(GuavaCollectors.toImmutableList());
     }
 
@@ -148,7 +146,7 @@
     }
 
     @Override
-    public Set<Resource> getAvailableResources(Resource parent) {
+    public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
         checkNotNull(parent);
 
         Set<Resource> children = store.getChildResources(parent);
@@ -159,7 +157,7 @@
     }
 
     @Override
-    public Set<Resource> getRegisteredResources(Resource parent) {
+    public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
         checkNotNull(parent);
 
         return store.getChildResources(parent);
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
index c985882..4083f5b 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
@@ -19,11 +19,16 @@
 import com.google.common.collect.ImmutableSet;
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.VlanId;
+import org.onosproject.net.newresource.ContinuousResourceId;
+import org.onosproject.net.newresource.DiscreteResource;
+import org.onosproject.net.newresource.DiscreteResourceId;
 import org.onosproject.net.newresource.ResourceAllocation;
 import org.onosproject.net.newresource.ResourceConsumer;
+import org.onosproject.net.newresource.ResourceId;
 import org.onosproject.net.newresource.ResourceListener;
 import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.ResourceService;
+import org.onosproject.net.newresource.Resources;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -70,17 +75,21 @@
     }
 
     @Override
-    public List<ResourceAllocation> getResourceAllocations(Resource resource) {
-        return Optional.ofNullable(assignment.get(resource))
-                .map(x -> ImmutableList.of(new ResourceAllocation(resource, x)))
+    public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+        if (id instanceof ContinuousResourceId) {
+            return ImmutableList.of();
+        }
+        DiscreteResource discrete = Resources.discrete((DiscreteResourceId) id).resource();
+        return Optional.ofNullable(assignment.get(discrete))
+                .map(x -> ImmutableList.of(new ResourceAllocation(discrete, x)))
                 .orElse(ImmutableList.of());
     }
 
     @Override
-    public <T> Collection<ResourceAllocation> getResourceAllocations(Resource parent, Class<T> cls) {
+    public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
         return assignment.entrySet().stream()
                 .filter(x -> x.getKey().parent().isPresent())
-                .filter(x -> x.getKey().parent().get().equals(parent))
+                .filter(x -> x.getKey().parent().get().id().equals(parent))
                 .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
                 .collect(Collectors.toList());
     }
@@ -94,16 +103,15 @@
     }
 
     @Override
-    public Set<Resource> getAvailableResources(Resource parent) {
-
-        Collection<Resource> resources = new HashSet<Resource>();
-        resources.add(parent.child(VlanId.vlanId((short) 10)));
-        resources.add(parent.child(MplsLabel.mplsLabel(10)));
+    public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
+        Collection<Resource> resources = new HashSet<>();
+        resources.add(Resources.discrete(parent).resource().child(VlanId.vlanId((short) 10)));
+        resources.add(Resources.discrete(parent).resource().child(MplsLabel.mplsLabel(10)));
         return ImmutableSet.copyOf(resources);
     }
 
     @Override
-    public Set<Resource> getRegisteredResources(Resource parent) {
+    public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
         return getAvailableResources(parent);
     }
 
diff --git a/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
index b5aa160..afac1bc 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
@@ -27,7 +27,9 @@
 import org.onlab.util.GuavaCollectors;
 import org.onlab.util.Tools;
 import org.onosproject.net.newresource.ContinuousResource;
+import org.onosproject.net.newresource.ContinuousResourceId;
 import org.onosproject.net.newresource.DiscreteResource;
+import org.onosproject.net.newresource.DiscreteResourceId;
 import org.onosproject.net.newresource.ResourceAllocation;
 import org.onosproject.net.newresource.ResourceConsumer;
 import org.onosproject.net.newresource.ResourceEvent;
@@ -35,6 +37,7 @@
 import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.ResourceStore;
 import org.onosproject.net.newresource.ResourceStoreDelegate;
+import org.onosproject.net.newresource.Resources;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.ConsistentMap;
@@ -86,60 +89,63 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService service;
 
-    private ConsistentMap<DiscreteResource, ResourceConsumer> discreteConsumers;
-    private ConsistentMap<ResourceId, ContinuousResourceAllocation> continuousConsumers;
-    private ConsistentMap<DiscreteResource, Set<Resource>> childMap;
+    private ConsistentMap<DiscreteResourceId, ResourceConsumer> discreteConsumers;
+    private ConsistentMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumers;
+    private ConsistentMap<DiscreteResourceId, Set<Resource>> childMap;
 
     @Activate
     public void activate() {
-        discreteConsumers = service.<DiscreteResource, ResourceConsumer>consistentMapBuilder()
+        discreteConsumers = service.<DiscreteResourceId, ResourceConsumer>consistentMapBuilder()
                 .withName(DISCRETE_CONSUMER_MAP)
                 .withSerializer(SERIALIZER)
                 .build();
-        continuousConsumers = service.<ResourceId, ContinuousResourceAllocation>consistentMapBuilder()
+        continuousConsumers = service.<ContinuousResourceId, ContinuousResourceAllocation>consistentMapBuilder()
                 .withName(CONTINUOUS_CONSUMER_MAP)
                 .withSerializer(SERIALIZER)
                 .build();
-        childMap = service.<DiscreteResource, Set<Resource>>consistentMapBuilder()
+        childMap = service.<DiscreteResourceId, Set<Resource>>consistentMapBuilder()
                 .withName(CHILD_MAP)
                 .withSerializer(SERIALIZER)
                 .build();
 
-        Tools.retryable(() -> childMap.put(Resource.ROOT, new LinkedHashSet<>()),
+        Tools.retryable(() -> childMap.put(Resource.ROOT.id(), new LinkedHashSet<>()),
                         ConsistentMapException.class, MAX_RETRIES, RETRY_DELAY);
         log.info("Started");
     }
 
+    // Computational complexity: O(1) if the resource is discrete type.
+    // O(n) if the resource is continuous type where n is the number of the existing allocations for the resource
     @Override
-    public List<ResourceConsumer> getConsumers(Resource resource) {
-        checkNotNull(resource);
-        checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
+    public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+        checkNotNull(id);
+        checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
 
-        if (resource instanceof DiscreteResource) {
-            return getConsumers((DiscreteResource) resource);
+        if (id instanceof DiscreteResourceId) {
+            return getResourceAllocations((DiscreteResourceId) id);
         } else {
-            return getConsumers((ContinuousResource) resource);
+            return getResourceAllocations((ContinuousResourceId) id);
         }
     }
 
-    private List<ResourceConsumer> getConsumers(DiscreteResource resource) {
+    // computational complexity: O(1)
+    private List<ResourceAllocation> getResourceAllocations(DiscreteResourceId resource) {
         Versioned<ResourceConsumer> consumer = discreteConsumers.get(resource);
         if (consumer == null) {
             return ImmutableList.of();
         }
 
-        return ImmutableList.of(consumer.value());
+        return ImmutableList.of(new ResourceAllocation(Resources.discrete(resource).resource(), consumer.value()));
     }
 
-    private List<ResourceConsumer> getConsumers(ContinuousResource resource) {
-        Versioned<ContinuousResourceAllocation> allocations = continuousConsumers.get(resource.id());
+    // computational complexity: O(n) where n is the number of the existing allocations for the resource
+    private List<ResourceAllocation> getResourceAllocations(ContinuousResourceId resource) {
+        Versioned<ContinuousResourceAllocation> allocations = continuousConsumers.get(resource);
         if (allocations == null) {
             return ImmutableList.of();
         }
 
         return allocations.value().allocations().stream()
-                .filter(x -> x.resource().equals(resource))
-                .map(ResourceAllocation::consumer)
+                .filter(x -> x.resource().id().equals(resource))
                 .collect(GuavaCollectors.toImmutableList());
     }
 
@@ -153,7 +159,7 @@
         TransactionContext tx = service.transactionContextBuilder().build();
         tx.begin();
 
-        TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+        TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
                 tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
 
         Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
@@ -166,7 +172,7 @@
                 return abortTransaction(tx);
             }
 
-            if (!appendValues(childTxMap, entry.getKey(), entry.getValue())) {
+            if (!appendValues(childTxMap, entry.getKey().id(), entry.getValue())) {
                 return abortTransaction(tx);
             }
         }
@@ -189,26 +195,27 @@
         TransactionContext tx = service.transactionContextBuilder().build();
         tx.begin();
 
-        TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+        TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
                 tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
-        TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+        TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
                 tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
-        TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+        TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
                 tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
 
         // Extract Discrete instances from resources
-        Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
+        Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
                 .filter(x -> x.parent().isPresent())
-                .collect(Collectors.groupingBy(x -> x.parent().get()));
+                .collect(Collectors.groupingBy(x -> x.parent().get().id()));
 
         // even if one of the resources is allocated to a consumer,
         // all unregistrations are regarded as failure
-        for (Map.Entry<DiscreteResource, List<Resource>> entry: resourceMap.entrySet()) {
+        for (Map.Entry<DiscreteResourceId, List<Resource>> entry: resourceMap.entrySet()) {
             boolean allocated = entry.getValue().stream().anyMatch(x -> {
                 if (x instanceof DiscreteResource) {
-                    return discreteConsumerTxMap.get((DiscreteResource) x) != null;
+                    return discreteConsumerTxMap.get(((DiscreteResource) x).id()) != null;
                 } else if (x instanceof ContinuousResource) {
-                    ContinuousResourceAllocation allocations = continuousConsumerTxMap.get(x.id());
+                    ContinuousResourceAllocation allocations =
+                            continuousConsumerTxMap.get(((ContinuousResource) x).id());
                     return allocations != null && !allocations.allocations().isEmpty();
                 } else {
                     return false;
@@ -247,11 +254,11 @@
         TransactionContext tx = service.transactionContextBuilder().build();
         tx.begin();
 
-        TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+        TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
                 tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
-        TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+        TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
                 tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
-        TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+        TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
                 tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
 
         for (Resource resource: resources) {
@@ -260,7 +267,7 @@
                     return abortTransaction(tx);
                 }
 
-                ResourceConsumer oldValue = discreteConsumerTxMap.put((DiscreteResource) resource, consumer);
+                ResourceConsumer oldValue = discreteConsumerTxMap.put(((DiscreteResource) resource).id(), consumer);
                 if (oldValue != null) {
                     return abortTransaction(tx);
                 }
@@ -295,9 +302,9 @@
         TransactionContext tx = service.transactionContextBuilder().build();
         tx.begin();
 
-        TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+        TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
                 tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
-        TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+        TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
                 tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
         Iterator<Resource> resourceIte = resources.iterator();
         Iterator<ResourceConsumer> consumerIte = consumers.iterator();
@@ -309,7 +316,7 @@
             if (resource instanceof DiscreteResource) {
                 // if this single release fails (because the resource is allocated to another consumer,
                 // the whole release fails
-                if (!discreteConsumerTxMap.remove((DiscreteResource) resource, consumer)) {
+                if (!discreteConsumerTxMap.remove(((DiscreteResource) resource).id(), consumer)) {
                     return abortTransaction(tx);
                 }
             } else if (resource instanceof ContinuousResource) {
@@ -330,20 +337,23 @@
         return tx.commit();
     }
 
+    // computational complexity: O(1) if the resource is discrete type.
+    // O(n) if the resource is continuous type where n is the number of the children of
+    // the specified resource's parent
     @Override
     public boolean isAvailable(Resource resource) {
         checkNotNull(resource);
         checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
 
         // check if it's registered or not.
-        Versioned<Set<Resource>> v = childMap.get(resource.parent().get());
+        Versioned<Set<Resource>> v = childMap.get(resource.parent().get().id());
         if (v == null || !v.value().contains(resource)) {
             return false;
         }
 
         if (resource instanceof DiscreteResource) {
             // check if already consumed
-            return getConsumers((DiscreteResource) resource).isEmpty();
+            return getResourceAllocations(resource.id()).isEmpty();
         } else {
             ContinuousResource requested = (ContinuousResource) resource;
             ContinuousResource registered = v.value().stream()
@@ -360,6 +370,7 @@
         }
     }
 
+    // computational complexity: O(n) where n is the number of existing allocations for the resource
     private boolean isAvailable(ContinuousResource resource) {
         Versioned<ContinuousResourceAllocation> allocation = continuousConsumers.get(resource.id());
         if (allocation == null) {
@@ -370,6 +381,8 @@
         return hasEnoughResource(allocation.value().original(), resource, allocation.value());
     }
 
+    // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
+    // and m is the number of allocations for all continuous resources
     @Override
     public Collection<Resource> getResources(ResourceConsumer consumer) {
         checkNotNull(consumer);
@@ -378,7 +391,8 @@
         // TODO: revisit for better backend data structure
         Stream<DiscreteResource> discreteStream = discreteConsumers.entrySet().stream()
                 .filter(x -> x.getValue().value().equals(consumer))
-                .map(Map.Entry::getKey);
+                .map(Map.Entry::getKey)
+                .map(x -> Resources.discrete(x).resource());
 
         Stream<ContinuousResource> continuousStream = continuousConsumers.values().stream()
                 .flatMap(x -> x.value().allocations().stream()
@@ -389,15 +403,12 @@
         return Stream.concat(discreteStream, continuousStream).collect(Collectors.toList());
     }
 
+    // computational complexity: O(n)
     @Override
-    public Set<Resource> getChildResources(Resource parent) {
+    public Set<Resource> getChildResources(DiscreteResourceId parent) {
         checkNotNull(parent);
-        if (!(parent instanceof DiscreteResource)) {
-            // only Discrete resource can have child resource
-            return ImmutableSet.of();
-        }
 
-        Versioned<Set<Resource>> children = childMap.get((DiscreteResource) parent);
+        Versioned<Set<Resource>> children = childMap.get(parent);
         if (children == null) {
             return ImmutableSet.of();
         }
@@ -405,13 +416,13 @@
         return children.value();
     }
 
+    // computational complexity: O(n) where n is the number of the children of the parent
     @Override
-    public <T> Collection<Resource> getAllocatedResources(Resource parent, Class<T> cls) {
+    public <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
         checkNotNull(parent);
         checkNotNull(cls);
-        checkArgument(parent instanceof DiscreteResource);
 
-        Versioned<Set<Resource>> children = childMap.get((DiscreteResource) parent);
+        Versioned<Set<Resource>> children = childMap.get(parent);
         if (children == null) {
             return ImmutableList.of();
         }
@@ -419,11 +430,11 @@
         Stream<DiscreteResource> discrete = children.value().stream()
                 .filter(x -> x.last().getClass().equals(cls))
                 .filter(x -> x instanceof DiscreteResource)
-                .map(x -> (DiscreteResource) x)
-                .filter(discreteConsumers::containsKey);
+                .map(x -> ((DiscreteResource) x))
+                .filter(x -> discreteConsumers.containsKey(x.id()));
 
         Stream<ContinuousResource> continuous = children.value().stream()
-                .filter(x -> x.id().equals(parent.id().child(cls)))
+                .filter(x -> x.id().equals(parent.child(cls)))
                 .filter(x -> x instanceof ContinuousResource)
                 .map(x -> (ContinuousResource) x)
                 .filter(x -> continuousConsumers.containsKey(x.id()))
@@ -445,7 +456,8 @@
     }
 
     // Appends the specified ResourceAllocation to the existing values stored in the map
-    private boolean appendValue(TransactionalMap<ResourceId, ContinuousResourceAllocation> map,
+    // computational complexity: O(n) where n is the number of the elements in the associated allocation
+    private boolean appendValue(TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> map,
                                 ContinuousResource original, ResourceAllocation value) {
         ContinuousResourceAllocation oldValue = map.putIfAbsent(original.id(),
                 new ContinuousResourceAllocation(original, ImmutableList.of(value)));
@@ -474,8 +486,9 @@
      * @param values values to be appended
      * @return true if the operation succeeds, false otherwise.
      */
-    private boolean appendValues(TransactionalMap<DiscreteResource, Set<Resource>> map,
-                                 DiscreteResource key, List<Resource> values) {
+    // computational complexity: O(n) where n is the number of the specified value
+    private boolean appendValues(TransactionalMap<DiscreteResourceId, Set<Resource>> map,
+                                 DiscreteResourceId key, List<Resource> values) {
         Set<Resource> oldValues = map.putIfAbsent(key, new LinkedHashSet<>(values));
         if (oldValues == null) {
             return true;
@@ -500,8 +513,9 @@
      * @param values values to be removed
      * @return true if the operation succeeds, false otherwise
      */
-    private boolean removeValues(TransactionalMap<DiscreteResource, Set<Resource>> map,
-                                 DiscreteResource key, List<Resource> values) {
+    // computational complexity: O(n) where n is the number of the specified values
+    private boolean removeValues(TransactionalMap<DiscreteResourceId, Set<Resource>> map,
+                                 DiscreteResourceId key, List<Resource> values) {
         Set<Resource> oldValues = map.putIfAbsent(key, new LinkedHashSet<>());
         if (oldValues == null) {
             log.trace("No-Op removing values. key {} did not exist", key);
@@ -528,14 +542,16 @@
      * @return the resource which is regarded as the same as the specified resource
      */
     // Naive implementation, which traverses all elements in the list
+    // computational complexity: O(n) where n is the number of elements
+    // in the associated set
     private <T extends Resource> Optional<T> lookup(
-            TransactionalMap<DiscreteResource, Set<Resource>> map, T resource) {
+            TransactionalMap<DiscreteResourceId, Set<Resource>> map, T resource) {
         // if it is root, always returns itself
         if (!resource.parent().isPresent()) {
             return Optional.of(resource);
         }
 
-        Set<Resource> values = map.get(resource.parent().get());
+        Set<Resource> values = map.get(resource.parent().get().id());
         if (values == null) {
             return Optional.empty();
         }
@@ -557,6 +573,7 @@
      * @param allocation current allocation of the resource
      * @return true if there is enough resource volume. Otherwise, false.
      */
+    // computational complexity: O(n) where n is the number of allocations
     private boolean hasEnoughResource(ContinuousResource original,
                                       ContinuousResource request,
                                       ContinuousResourceAllocation allocation) {