[ONOS-6248] VPLS refactoring

Change-Id: I8ffb2199ca108ad8dfe271681068636fc4af2a40
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
index d4bfa8d..4718453 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
@@ -15,24 +15,24 @@
  */
 package org.onosproject.vpls.cli;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.EncapsulationType;
-import org.onosproject.vpls.config.VplsConfigService;
+import org.onosproject.vpls.api.VplsData;
+import org.onosproject.vpls.api.Vpls;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 
+
 /**
  * CLI to interact with the VPLS application.
  */
@@ -85,7 +85,8 @@
                     " not found" + RESET;
 
     private static final String VPLS_DISPLAY = "VPLS name: " + BOLD +
-            "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s";
+            "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s\n" +
+            "State: %s";
 
     private static final String VPLS_NOT_FOUND =
             COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
@@ -93,15 +94,13 @@
 
     private static final String IFACE_NOT_ASSOCIATED =
             COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
-                    " cannot be removed from VPLS " + BOLD + "%s" + RESET +
-                    COLOR_ERROR + ". The interface is associated to another" +
-                    "VPLS (" + BOLD + "%s" + RESET + COLOR_ERROR + ")" + RESET;
+                    " cannot be removed from VPLS " + BOLD + "%s" + RESET + ".";
 
-    private static VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
+    protected static Vpls vpls;
+    protected static InterfaceService interfaceService;
 
     @Argument(index = 0, name = "command", description = "Command name (add-if|" +
-            "clean|create|delete|list|rem-if|set-encap|show)",
+            "create|delete|list|rem-if|set-encap|show)",
             required = true, multiValued = false)
     String command = null;
 
@@ -116,15 +115,19 @@
 
     @Override
     protected void execute() {
+        if (vpls == null) {
+            vpls = get(Vpls.class);
+        }
+        if (interfaceService == null) {
+            interfaceService = get(InterfaceService.class);
+        }
+
         VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
         if (enumCommand != null) {
             switch (enumCommand) {
                 case ADD_IFACE:
                     addIface(vplsName, optArg);
                     break;
-                case CLEAN:
-                    clean();
-                    break;
                 case CREATE:
                     create(vplsName);
                     break;
@@ -143,6 +146,9 @@
                 case SHOW:
                     show(vplsName);
                     break;
+                case CLEAN:
+                    cleanVpls();
+                    break;
                 default:
                     print(VPLS_COMMAND_NOT_FOUND, command);
             }
@@ -157,7 +163,7 @@
      * @param vplsName the name of the VLPS
      * @param ifaceName the name of the interface to add
      */
-    private void addIface(String vplsName, String ifaceName) {
+    protected void addIface(String vplsName, String ifaceName) {
         if (vplsName == null) {
             print(INSERT_VPLS_NAME);
             return;
@@ -166,28 +172,24 @@
             print(INSERT_INTERFACE);
             return;
         }
-        if (!vplsExists(vplsName)) {
+
+        Interface iface = getInterface(ifaceName);
+        VplsData vplsData = vpls.getVpls(vplsName);
+
+        if (vplsData == null) {
             print(VPLS_NOT_FOUND, vplsName);
             return;
         }
-        if (!ifaceExists(ifaceName)) {
+        if (iface == null) {
             print(IFACE_NOT_FOUND, ifaceName);
             return;
         }
-        if (isIfaceAssociated(ifaceName)) {
+        if (isIfaceAssociated(iface)) {
             print(IFACE_ALREADY_ASSOCIATED,
-                  ifaceName, vplsNameFromIfaceName(ifaceName));
+                  ifaceName, getVplsByInterface(iface).name());
             return;
         }
-
-        vplsConfigService.addIface(vplsName, ifaceName);
-    }
-
-    /**
-     * Cleans the VPLS configuration.
-     */
-    private void clean() {
-        vplsConfigService.cleanVplsConfig();
+        vpls.addInterface(vplsData, iface);
     }
 
     /**
@@ -195,16 +197,17 @@
      *
      * @param vplsName the name of the VLPS
      */
-    private void create(String vplsName) {
+    protected void create(String vplsName) {
         if (vplsName == null || vplsName.isEmpty()) {
             print(INSERT_VPLS_NAME);
             return;
         }
-        if (vplsExists(vplsName)) {
+        VplsData vplsData = vpls.getVpls(vplsName);
+        if (vplsData != null) {
             print(VPLS_ALREADY_EXISTS, vplsName);
             return;
         }
-        vplsConfigService.addVpls(vplsName, Sets.newHashSet(), null);
+        vpls.createVpls(vplsName, EncapsulationType.NONE);
     }
 
     /**
@@ -212,23 +215,26 @@
      *
      * @param vplsName the name of the VLPS
      */
-    private void delete(String vplsName) {
+    protected void delete(String vplsName) {
         if (vplsName == null) {
             print(INSERT_VPLS_NAME);
             return;
         }
-        if (!vplsExists(vplsName)) {
+        VplsData vplsData = vpls.getVpls(vplsName);
+        if (vplsData == null) {
             print(VPLS_NOT_FOUND, vplsName);
             return;
         }
-        vplsConfigService.removeVpls(vplsName);
+        vpls.removeVpls(vplsData);
     }
 
     /**
      * Lists the configured VPLSs.
      */
-    private void list() {
-        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
+    protected void list() {
+        List<String> vplsNames = vpls.getAllVpls().stream()
+                .map(VplsData::name)
+                .collect(Collectors.toList());
         Collections.sort(vplsNames);
 
         vplsNames.forEach(vpls -> {
@@ -242,7 +248,7 @@
      * @param vplsName the name of the VLPS
      * @param ifaceName the name of the interface to remove
      */
-    private void removeIface(String vplsName, String ifaceName) {
+    protected void removeIface(String vplsName, String ifaceName) {
         if (vplsName == null) {
             print(INSERT_VPLS_NAME);
             return;
@@ -251,20 +257,21 @@
             print(INSERT_INTERFACE);
             return;
         }
-        if (!vplsExists(vplsName)) {
+        VplsData vplsData = vpls.getVpls(vplsName);
+        Interface iface = getInterface(ifaceName);
+        if (vplsData == null) {
             print(VPLS_NOT_FOUND, vplsName);
             return;
         }
-        if (!ifaceExists(ifaceName)) {
+        if (iface == null) {
             print(IFACE_NOT_FOUND, ifaceName);
             return;
         }
-        String vplsNameFromIfaceName = vplsNameFromIfaceName(ifaceName);
-        if (!vplsNameFromIfaceName.equals(vplsName)) {
-            print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName, vplsNameFromIfaceName);
+        if (!vplsData.interfaces().contains(iface)) {
+            print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName);
             return;
         }
-        vplsConfigService.removeIface(ifaceName);
+        vpls.removeInterface(vplsData, iface);
     }
 
     /**
@@ -273,7 +280,7 @@
      * @param vplsName the name of the VPLS
      * @param encap the encapsulation type
      */
-    private void setEncap(String vplsName, String encap) {
+    protected void setEncap(String vplsName, String encap) {
         if (vplsName == null) {
             print(INSERT_VPLS_NAME);
             return;
@@ -282,7 +289,8 @@
             print(INSERT_ENCAP_TYPE);
             return;
         }
-        if (!vplsExists(vplsName)) {
+        VplsData vplsData = vpls.getVpls(vplsName);
+        if (vplsData == null) {
             print(VPLS_NOT_FOUND, vplsName);
             return;
         }
@@ -292,7 +300,7 @@
             print(ENCAP_NOT_FOUND, encap);
             return;
         }
-        vplsConfigService.setEncap(vplsName, encap);
+        vpls.setEncapsulationType(vplsData, encapType);
     }
 
     /**
@@ -300,113 +308,88 @@
      *
      * @param vplsName the name of the VPLS
      */
-    private void show(String vplsName) {
-        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
-        Collections.sort(vplsNames);
-
-        Map<String, EncapsulationType> encapByVplsName =
-                vplsConfigService.encapByVplsName();
-
+    protected void show(String vplsName) {
         if (!isNullOrEmpty(vplsName)) {
             // A VPLS name is provided. Check first if the VPLS exists
-            if (vplsExists(vplsName)) {
+            VplsData vplsData = vpls.getVpls(vplsName);
+            if (vplsData != null) {
+                Set<String> ifaceNames = vplsData.interfaces().stream()
+                        .map(Interface::name)
+                        .collect(Collectors.toSet());
                 print(VPLS_DISPLAY,
                       vplsName,
-                      ifacesFromVplsName(vplsName).toString(),
-                      encapByVplsName.get(vplsName).toString());
+                      ifaceNames,
+                      vplsData.encapsulationType().toString(),
+                      vplsData.state());
             } else {
                 print(VPLS_NOT_FOUND, vplsName);
             }
         } else {
+            Collection<VplsData> vplses = vpls.getAllVpls();
             // No VPLS names are provided. Display all VPLSs configured
             print(SEPARATOR);
-            vplsNames.forEach(v -> {
+            vplses.forEach(vplsData -> {
+                Set<String> ifaceNames = vplsData.interfaces().stream()
+                        .map(Interface::name)
+                        .collect(Collectors.toSet());
                 print(VPLS_DISPLAY,
-                      v,
-                      ifacesFromVplsName(v).toString(),
-                      encapByVplsName.get(v).toString());
+                      vplsData.name(),
+                      ifaceNames,
+                      vplsData.encapsulationType().toString(),
+                      vplsData.state());
                 print(SEPARATOR);
             });
         }
     }
 
     /**
-     * States if a VPLS exists or not.
-     *
-     * @param vplsName the name of the VPLS
-     * @return true if the VPLS exists; false otherwise
+     * Remove all VPLS.
      */
-    private static boolean vplsExists(String vplsName) {
-        return vplsConfigService.vplsNames().contains(vplsName);
+    protected void cleanVpls() {
+        vpls.removeAllVpls();
     }
 
-    /**
-     * States if an interface is defined or not in the system.
-     *
-     * @param ifaceName the name of the interface
-     * @return true if the interface is defined; false otherwise
-     */
-    private static boolean ifaceExists(String ifaceName) {
-        return vplsConfigService.allIfaces()
-                .stream()
-                .anyMatch(iface -> iface.name().equals(ifaceName));
-    }
 
     /**
      * States if an interface is already associated to a VPLS.
      *
-     * @param ifaceName the name of the interface
+     * @param iface the interface
      * @return true if the interface is already associated to a VPLS; false
      * otherwise
      */
-    private static boolean isIfaceAssociated(String ifaceName) {
-        return vplsConfigService.ifaces()
+    private static boolean isIfaceAssociated(Interface iface) {
+        return vpls.getAllVpls()
                 .stream()
-                .anyMatch(iface -> iface.name().equals(ifaceName));
+                .map(VplsData::interfaces)
+                .flatMap(Collection::stream)
+                .anyMatch(iface::equals);
     }
 
     /**
-     * Returns the name of a VPLS, given the name of an interface associated to
-     * it.
+     * Gets a network interface by given interface name.
      *
-     * @param ifaceName the name of the interface
-     * @return the name of the VPLS that has the interface configured; null if
-     * the interface does not exist or is not associated to any VPLS
+     * @param interfaceName the interface name
+     * @return the network interface
      */
-    private static String vplsNameFromIfaceName(String ifaceName) {
-        String vplsName = null;
-
-        Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
-                .entries()
-                .stream()
-                .filter((entry -> entry.getValue().name().equals(ifaceName)))
-                .map(Map.Entry::getKey)
-                .findFirst();
-
-        if (optVplsName.isPresent()) {
-            vplsName = optVplsName.get();
-        }
-
-        return vplsName;
+    private Interface getInterface(String interfaceName) {
+        // FIXME: only returns first interface it found
+        // multiple interface with same name not support
+        return interfaceService.getInterfaces().stream()
+                .filter(iface -> iface.name().equals(interfaceName))
+                .findFirst()
+                .orElse(null);
     }
 
     /**
-     * Returns a list of interfaces associated to a VPLS, given a VPLS name.
+     * Gets a VPLS related to the network interface.
      *
-     * @param vplsName the name of the VPLS
-     * @return the set of interfaces associated to the given VPLS; null if the
-     * VPLS is not found
+     * @param iface the network interface
+     * @return the VPLS related to the network interface
      */
-    private static Set<String> ifacesFromVplsName(String vplsName) {
-        if (!vplsExists(vplsName)) {
-            return null;
-        }
-        SetMultimap<String, Interface> ifacesByVplsName =
-                vplsConfigService.ifacesByVplsName();
-        Set<String> ifaceNames = Sets.newHashSet();
-
-        ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));
-
-        return ifaceNames;
+    private VplsData getVplsByInterface(Interface iface) {
+        return vpls.getAllVpls().stream()
+                .filter(vplsData -> vplsData.interfaces().contains(iface))
+                .findFirst()
+                .orElse(null);
     }
 }
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java
index dfdaadf..c1ccb2b 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java
@@ -25,13 +25,13 @@
  */
 public enum VplsCommandEnum {
     ADD_IFACE("add-if"),
-    CLEAN("clean"),
     CREATE("create"),
     DELETE("delete"),
     LIST("list"),
     REMOVE_IFACE("rem-if"),
     SET_ENCAP("set-encap"),
-    SHOW("show");
+    SHOW("show"),
+    CLEAN("clean");
 
     private final String command;
 
@@ -40,7 +40,7 @@
      *
      * @param command the text representing the command
      */
-    private VplsCommandEnum(final String command) {
+    VplsCommandEnum(final String command) {
         this.command = command;
     }
 
@@ -56,7 +56,7 @@
      */
     public static List<String> toStringList() {
         return Arrays.stream(values())
-                .map(c -> c.toString())
+                .map(VplsCommandEnum::toString)
                 .collect(Collectors.toCollection(ArrayList::new));
     }
 
@@ -71,7 +71,7 @@
     public static VplsCommandEnum enumFromString(String command) {
         if (command != null && !command.isEmpty()) {
             for (VplsCommandEnum c : values()) {
-                if (command.toString().equalsIgnoreCase(c.toString())) {
+                if (command.equalsIgnoreCase(c.toString())) {
                     return c;
                 }
             }
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java
index cfe08b7..2b198a9 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java
@@ -16,6 +16,7 @@
 package org.onosproject.vpls.cli.completer;
 
 import com.google.common.collect.Lists;
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
 import org.onosproject.cli.AbstractChoicesCompleter;
 import org.onosproject.vpls.cli.VplsCommandEnum;
 
@@ -29,17 +30,19 @@
 
     @Override
     public List<String> choices() {
-        List<String> argumentList =
-                Lists.newArrayList(getArgumentList().getArguments());
+        ArgumentCompleter.ArgumentList argumentList = getArgumentList();
+        if (argumentList == null) {
+            return Collections.emptyList();
+        }
+        List<String> argList = Lists.newArrayList(argumentList.getArguments());
         String argOne = null;
-        if (argumentList.size() > 1) {
-            argOne = argumentList.get(1);
+        if (argList.size() > 1) {
+            argOne = argList.get(1);
         }
         VplsCommandEnum vplsCommandEnum = VplsCommandEnum.enumFromString(argOne);
         if (vplsCommandEnum != null) {
             switch (vplsCommandEnum) {
                 case CREATE:
-                case CLEAN:
                 case LIST:
                     return Collections.emptyList();
                 default:
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
index ab2479b..6900880 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
@@ -15,11 +15,13 @@
  */
 package org.onosproject.vpls.cli.completer;
 
-import com.google.common.collect.Lists;
 import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.vpls.config.VplsConfigService;
+import org.onosproject.vpls.api.Vpls;
+import org.onosproject.vpls.api.VplsData;
 
+import java.util.Collection;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import static org.onosproject.cli.AbstractShellCommand.get;
 
@@ -28,9 +30,14 @@
  */
 public class VplsNameCompleter extends AbstractChoicesCompleter {
 
+    protected static Vpls vpls;
+
     @Override
     public List<String> choices() {
-        VplsConfigService vplsConfigService = get(VplsConfigService.class);
-        return Lists.newArrayList(vplsConfigService.vplsNames());
+        if (vpls == null) {
+            vpls = get(Vpls.class);
+        }
+        Collection<VplsData> vplses = vpls.getAllVpls();
+        return vplses.stream().map(VplsData::name).collect(Collectors.toList());
     }
 }
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
index 5b60352..7058cdc 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
@@ -16,15 +16,17 @@
 package org.onosproject.vpls.cli.completer;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 import org.apache.karaf.shell.console.completer.ArgumentCompleter;
 import org.onosproject.cli.AbstractChoicesCompleter;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.EncapsulationType;
+import org.onosproject.vpls.api.Vpls;
+import org.onosproject.vpls.api.VplsData;
 import org.onosproject.vpls.cli.VplsCommandEnum;
-import org.onosproject.vpls.config.VplsConfigService;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -36,22 +38,29 @@
  * VPLS optional argument completer.
  */
 public class VplsOptArgCompleter extends AbstractChoicesCompleter {
+    protected static Vpls vpls;
+    protected static InterfaceService interfaceService;
 
     @Override
     public List<String> choices() {
-        VplsConfigService vplsConfigService = get(VplsConfigService.class);
-        List<String> argumentList =
-                Lists.newArrayList(getArgumentList().getArguments());
-        String argOne = argumentList.get(1);
+        if (vpls == null) {
+            vpls = get(Vpls.class);
+        }
+        ArgumentCompleter.ArgumentList argumentList = getArgumentList();
+        if (argumentList == null) {
+            return Collections.emptyList();
+        }
+        List<String> argList = Lists.newArrayList(argumentList.getArguments());
+        String argOne = argList.get(1);
         VplsCommandEnum vplsCommandEnum = VplsCommandEnum.enumFromString(argOne);
         if (vplsCommandEnum != null) {
             switch (vplsCommandEnum) {
                 case ADD_IFACE:
-                    return availableIfaces(vplsConfigService);
+                    return availableIfaces();
                 case SET_ENCAP:
                     return encap();
                 case REMOVE_IFACE:
-                    return vplsIfaces(vplsConfigService);
+                    return vplsIfaces();
                 default:
                     return Collections.emptyList();
             }
@@ -64,21 +73,27 @@
      *
      * @return the list of interfaces not yet assigned to any VPLS
      */
-    private List<String> availableIfaces(VplsConfigService vplsConfigService) {
-        List<String> ifacesAvailable = Lists.newArrayList();
-        Set<Interface> allIfaces = Sets.newHashSet(vplsConfigService.allIfaces());
-        Set<Interface> usedIfaces = Sets.newHashSet(vplsConfigService.ifaces());
+    private List<String> availableIfaces() {
+        if (interfaceService == null) {
+            interfaceService = get(InterfaceService.class);
+        }
 
-        allIfaces.removeAll(usedIfaces);
-        allIfaces.forEach(iface -> ifacesAvailable.add(iface.name()));
+        Set<Interface> allIfaces = interfaceService.getInterfaces();
+        Set<Interface> usedIfaces = vpls.getAllVpls().stream()
+                .map(VplsData::interfaces)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toSet());
 
-        return ifacesAvailable;
+        return allIfaces.stream()
+                .filter(iface -> !usedIfaces.contains(iface))
+                .map(Interface::name)
+                .collect(Collectors.toList());
     }
 
     /**
      * Returns the list of supported encapsulation types.
      *
-     * @return the list of supported encapsualtion types
+     * @return the list of supported encapsulation types
      */
     private List<String> encap() {
         return Arrays.stream(EncapsulationType.values())
@@ -91,15 +106,12 @@
      *
      * @return the list of interfaces associated to a VPLS
      */
-    private List<String> vplsIfaces(VplsConfigService vplsConfigService) {
+    private List<String> vplsIfaces() {
         ArgumentCompleter.ArgumentList list = getArgumentList();
         String vplsName = list.getArguments()[2];
-
-        List<String> vplsIfaces = Lists.newArrayList();
-
-        Set<Interface> connectPoints = vplsConfigService.ifaces(vplsName);
-        connectPoints.forEach(iface -> vplsIfaces.add(iface.name()));
-
-        return vplsIfaces;
+        VplsData vplsData = vpls.getVpls(vplsName);
+        return vplsData.interfaces().stream()
+                .map(Interface::name)
+                .collect(Collectors.toList());
     }
 }