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;
     }
 
     /**