clean up the SingleSwitchFibInstaller, added the predeactivate hook and modified unit test CORD-663

Change-Id: I8bf9dd4c7a6e9c42833a6f631bfceb85b7f3ddef
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
index f0649b9..4b2479e 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
@@ -32,6 +32,7 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onlab.util.Tools;
+import org.onosproject.app.ApplicationService;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
@@ -88,6 +89,7 @@
 public class SingleSwitchFibInstaller {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
+    private static final String APP_NAME = "org.onosproject.vrouter";
 
     private static final int PRIORITY_OFFSET = 100;
     private static final int PRIORITY_MULTIPLIER = 5;
@@ -118,6 +120,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ApplicationService applicationService;
+
     @Property(name = "routeToNextHop", boolValue = false,
             label = "Install a /32 route to each next hop")
     private boolean routeToNextHop = false;
@@ -133,6 +138,7 @@
 
     private ApplicationId coreAppId;
     private ApplicationId routerAppId;
+    private ApplicationId vrouterAppId;
 
     // Reference count for how many times a next hop is used by a route
     private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();
@@ -163,6 +169,7 @@
 
         coreAppId = coreService.registerApplication(CoreService.CORE_APP_NAME);
         routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID);
+        vrouterAppId = coreService.registerApplication(APP_NAME);
 
         networkConfigRegistry.registerConfigFactory(mcastConfigFactory);
 
@@ -173,6 +180,10 @@
 
         updateConfig();
 
+        applicationService.registerDeactivateHook(vrouterAppId, () -> {
+            this.cleanUp();
+        });
+
         log.info("Started");
     }
 
@@ -202,6 +213,17 @@
         log.info("routeToNextHop set to {}", routeToNextHop);
     }
 
+    //remove filtering objectives and routes before deactivate.
+    private void cleanUp() {
+        //clean up the routes.
+        for (Map.Entry<IpPrefix, IpAddress> routes: prefixToNextHop.entrySet()) {
+            deleteRoute(new ResolvedRoute(routes.getKey(), null, null));
+        }
+        //clean up the filtering objective for interfaces.
+        Set<Interface> intfs = getInterfaces();
+        processIntfFilters(false, intfs);
+    }
+
     private void updateConfig() {
         RouterConfig routerConfig =
                 networkConfigService.getConfig(routerAppId, RoutingService.ROUTER_CONFIG_CLASS);
@@ -226,22 +248,25 @@
 
     private void updateDevice() {
         if (deviceId != null && deviceService.isAvailable(deviceId)) {
-
-            Set<Interface> intfs;
-            if (interfaces.isEmpty()) {
-                intfs = interfaceService.getInterfaces();
-            } else {
-                // TODO need to fix by making interface names globally unique
-                intfs = interfaceService.getInterfaces().stream()
-                        .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
-                        .filter(intf -> interfaces.contains(intf.name()))
-                        .collect(Collectors.toSet());
-            }
-
+            Set<Interface> intfs = getInterfaces();
             processIntfFilters(true, intfs);
         }
     }
 
+    private Set<Interface> getInterfaces() {
+        Set<Interface> intfs;
+        if (interfaces.isEmpty()) {
+            intfs = interfaceService.getInterfaces();
+        } else {
+            // TODO need to fix by making interface names globally unique
+            intfs = interfaceService.getInterfaces().stream()
+                    .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
+                    .filter(intf -> interfaces.contains(intf.name()))
+                    .collect(Collectors.toSet());
+        }
+        return intfs;
+    }
+
     private void updateRoute(ResolvedRoute route) {
         addNextHop(route);
 
diff --git a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
index b1b80c5..69d2c34 100644
--- a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
+++ b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
@@ -26,6 +26,7 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.TestApplicationId;
+import org.onosproject.app.ApplicationService;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
@@ -102,12 +103,12 @@
     private static final InterfaceIpAddress INTF2 =
             InterfaceIpAddress.valueOf("192.168.20.2/24");
 
-
     private final Set<Interface> interfaces = Sets.newHashSet();
     private InterfaceService interfaceService;
     private NetworkConfigService networkConfigService;
     private NetworkConfigRegistry networkConfigRegistry;
     private FlowObjectiveService flowObjectiveService;
+    private ApplicationService applicationService;
     private DeviceService deviceService;
     private static final ApplicationId APPID = TestApplicationId.create("foo");
 
@@ -132,6 +133,8 @@
         networkConfigService = createMock(NetworkConfigService.class);
         networkConfigRegistry = createMock(NetworkConfigRegistry.class);
         flowObjectiveService = createMock(FlowObjectiveService.class);
+        applicationService = createNiceMock(ApplicationService.class);
+        replay(applicationService);
         deviceService = new TestDeviceService();
         CoreService coreService = createNiceMock(CoreService.class);
         expect(coreService.registerApplication(anyString())).andReturn(APPID).anyTimes();
@@ -141,6 +144,7 @@
         sSfibInstaller.networkConfigRegistry = networkConfigRegistry;
         sSfibInstaller.interfaceService = interfaceService;
         sSfibInstaller.flowObjectiveService = flowObjectiveService;
+        sSfibInstaller.applicationService = applicationService;
         sSfibInstaller.coreService = coreService;
         sSfibInstaller.routeService = new TestRouteService();
         sSfibInstaller.deviceService = deviceService;