Bugfix and cosmetic changes to resource subsystem

- Continuous resource was always considered not available
- Support querying for child resource against Continuous
   (result is no children)
- Resource equality to compare id and exact type

- Add missing information in Continuous resource toString()
- More concise String representation for ResourceId

- additional logging added during above bug investigation.

Change-Id: I58a95b95b91c246c3c5dbb136a1820f988c6fccd
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 72b9a57..15e4626 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
@@ -208,7 +208,11 @@
         if (this == obj) {
             return true;
         }
-        if (!(obj instanceof Resource)) {
+
+        if (obj == null) {
+            return false;
+        }
+        if (this.getClass() != obj.getClass()) {
             return false;
         }
         final Resource that = (Resource) obj;
@@ -259,25 +263,14 @@
 
         @Override
         public int hashCode() {
-            return Objects.hash(this.id(), this.value);
+            return super.hashCode();
         }
 
+        // explicitly overriding to express that we intentionally ignore
+        // `value` in equality comparison
         @Override
         public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-
-            if (!(obj instanceof Continuous)) {
-                return false;
-            }
-
-            if (!super.equals(obj)) {
-                return false;
-            }
-
-            final Continuous other = (Continuous) obj;
-            return Objects.equals(this.id(), other.id());
+            return super.equals(obj);
         }
 
         /**
@@ -288,6 +281,14 @@
         public double value() {
             return value;
         }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                    .add("id", id())
+                    .add("value", value)
+                    .toString();
+        }
     }
 
 }
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 c18e08b..6bfc3cc 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
@@ -16,7 +16,6 @@
 package org.onosproject.net.newresource;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -95,8 +94,6 @@
 
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("components", components)
-                .toString();
+        return components.toString();
     }
 }
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 96466d5..83ae6e0 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
@@ -34,12 +34,14 @@
 import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.ResourceStore;
 import org.onosproject.net.newresource.ResourceStoreDelegate;
+import org.slf4j.Logger;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * An implementation of ResourceService.
@@ -53,18 +55,24 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ResourceStore store;
 
+    private final Logger log = getLogger(getClass());
+
     private final ResourceStoreDelegate delegate = new InternalStoreDelegate();
 
     @Activate
     public void activate() {
         store.setDelegate(delegate);
         eventDispatcher.addSink(ResourceEvent.class, listenerRegistry);
+
+        log.info("Started");
     }
 
     @Deactivate
     public void deactivate() {
         store.unsetDelegate(delegate);
         eventDispatcher.removeSink(ResourceEvent.class);
+
+        log.info("Stopped");
     }
 
     @Override
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 707ce4b..817f8d2 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
@@ -143,6 +143,9 @@
     @Override
     public boolean register(List<Resource> resources) {
         checkNotNull(resources);
+        if (log.isTraceEnabled()) {
+            resources.forEach(r -> log.trace("registering {}", r));
+        }
 
         TransactionContext tx = service.transactionContextBuilder().build();
         tx.begin();
@@ -324,17 +327,36 @@
         checkNotNull(resource);
         checkArgument(resource instanceof Resource.Discrete || resource instanceof Resource.Continuous);
 
+        // check if it's registered or not.
+        Versioned<Set<Resource>> v = childMap.get(resource.parent().get());
+        if (v == null || !v.value().contains(resource)) {
+            return false;
+        }
+
         if (resource instanceof Resource.Discrete) {
+            // check if already consumed
             return getConsumer((Resource.Discrete) resource).isEmpty();
         } else {
-            return isAvailable((Resource.Continuous) resource);
+            Resource.Continuous requested = (Resource.Continuous) resource;
+            Resource.Continuous registered = v.value().stream()
+                    .filter(c -> c.equals(resource))
+                    .findFirst()
+                    .map(c -> (Resource.Continuous) c)
+                    .get();
+            if (registered.value() < requested.value()) {
+                // Capacity < requested, can never satisfy
+                return false;
+            }
+            // check if there's enough left
+            return isAvailable(requested);
         }
     }
 
     private boolean isAvailable(Resource.Continuous resource) {
         Versioned<ContinuousResourceAllocation> allocation = continuousConsumers.get(resource.id());
         if (allocation == null) {
-            return false;
+            // no allocation (=no consumer) full registered resources available
+            return true;
         }
 
         return hasEnoughResource(allocation.value().original(), resource, allocation.value());
@@ -362,7 +384,10 @@
     @Override
     public Collection<Resource> getChildResources(Resource parent) {
         checkNotNull(parent);
-        checkArgument(parent instanceof Resource.Discrete);
+        if (!(parent instanceof Resource.Discrete)) {
+            // only Discrete resource can have child resource
+            return ImmutableList.of();
+        }
 
         Versioned<Set<Resource>> children = childMap.get((Resource.Discrete) parent);
         if (children == null) {