bug fix: ResourceManager#unregisterResources only unregisters given resources and didn't unregister descendants (ONOS-3827).

Change-Id: I48956234553053e2a54834129b5f10357ca116ea
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
index 64691d5..f4ae805 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
@@ -41,10 +41,13 @@
 import org.onosproject.net.newresource.BandwidthCapacity;
 import org.onosproject.net.newresource.Resource;
 import org.onosproject.net.newresource.Resources;
+import org.onosproject.net.newresource.ResourceService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -60,6 +63,7 @@
     private static final Logger log = LoggerFactory.getLogger(ResourceDeviceListener.class);
 
     private final ResourceAdminService adminService;
+    private final ResourceService resourceService;
     private final DeviceService deviceService;
     private final DriverService driverService;
     private final NetworkConfigService netcfgService;
@@ -75,9 +79,11 @@
      * @param netcfgService {@link NetworkConfigService} to be used.
      * @param executor executor used for processing resource registration
      */
-    ResourceDeviceListener(ResourceAdminService adminService, DeviceService deviceService, DriverService driverService,
+    ResourceDeviceListener(ResourceAdminService adminService, ResourceService resourceService,
+                           DeviceService deviceService, DriverService driverService,
                            NetworkConfigService netcfgService, ExecutorService executor) {
         this.adminService = checkNotNull(adminService);
+        this.resourceService = checkNotNull(resourceService);
         this.deviceService = checkNotNull(deviceService);
         this.driverService = checkNotNull(driverService);
         this.netcfgService = checkNotNull(netcfgService);
@@ -123,7 +129,11 @@
     }
 
     private void unregisterDeviceResource(Device device) {
-        executor.submit(() -> adminService.unregisterResources(Resources.discrete(device.id()).resource()));
+        executor.submit(() -> {
+            Resource devResource = Resources.discrete(device.id()).resource();
+            List<Resource> allResources = getDescendantResources(devResource);
+            adminService.unregisterResources(allResources);
+        });
     }
 
     private void registerPortResource(Device device, Port port) {
@@ -175,8 +185,30 @@
     }
 
     private void unregisterPortResource(Device device, Port port) {
-        Resource resource = Resources.discrete(device.id(), port.number()).resource();
-        executor.submit(() -> adminService.unregisterResources(resource));
+        executor.submit(() -> {
+            Resource portResource = Resources.discrete(device.id(), port.number()).resource();
+            List<Resource> allResources = getDescendantResources(portResource);
+            adminService.unregisterResources(allResources);
+        });
+    }
+
+    // Returns list of all descendant resources of given resource, including itself.
+    private List<Resource> getDescendantResources(Resource parent) {
+        LinkedList<Resource> allResources = new LinkedList<>();
+        allResources.add(parent);
+
+        Set<Resource> nextResources = resourceService.getRegisteredResources(parent);
+        while (!nextResources.isEmpty()) {
+            Set<Resource> currentResources = nextResources;
+            // resource list should be ordered from leaf to root
+            allResources.addAll(0, currentResources);
+
+            nextResources = currentResources.stream()
+                    .flatMap(r -> resourceService.getRegisteredResources(r).stream())
+                    .collect(Collectors.toSet());
+        }
+
+        return allResources;
     }
 
     /**
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
index 27d5333..e2666dd 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
@@ -32,6 +32,7 @@
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.newresource.BandwidthCapacity;
 import org.onosproject.net.newresource.ResourceAdminService;
+import org.onosproject.net.newresource.ResourceService;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -53,6 +54,9 @@
     protected ResourceAdminService adminService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DriverService driverService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -87,7 +91,8 @@
         cfgListener = new ResourceNetworkConfigListener(adminService, cfgRegistry, executor);
         cfgRegistry.addListener(cfgListener);
 
-        deviceListener = new ResourceDeviceListener(adminService, deviceService, driverService, cfgRegistry, executor);
+        deviceListener = new ResourceDeviceListener(adminService, resourceService,
+                deviceService, driverService, cfgRegistry, executor);
         deviceService.addListener(deviceListener);
 
         // TODO Attempt initial registration of existing resources?