[ONOS-4387] Support for multiple selectors in mp2sp intents

Changes:
- Adds extension to mp2sp intents;
- Adds extension to linkcollection intents;
- Adds extension to mp2sp compiler;
- Adds extension to linkcollection compiler;
- Adds unit tests for both mp2sp and linkcollection intents;

Change-Id: I673c2b660d2364c510b1b3050ed3626ad2f37bda
diff --git a/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java b/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java
index 0c01543..d1fe612 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/MultiPointToSinglePointIntent.java
@@ -17,6 +17,7 @@
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import org.onosproject.core.ApplicationId;
@@ -26,6 +27,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -39,6 +41,10 @@
 
     private final Set<ConnectPoint> ingressPoints;
     private final ConnectPoint egressPoint;
+    /**
+     * To manage multiple selectors use case.
+     */
+    private final Map<ConnectPoint, TrafficSelector> ingressSelectors;
 
     /**
      * Creates a new multi-to-single point connectivity intent for the specified
@@ -52,19 +58,22 @@
      * @param egressPoint   port to which traffic will egress
      * @param constraints   constraints to apply to the intent
      * @param priority      priority to use for flows generated by this intent
+     * @param ingressSelectors map to store the association ingress to selector
      * @throws NullPointerException     if {@code ingressPoints} or
      *                                  {@code egressPoint} is null.
      * @throws IllegalArgumentException if the size of {@code ingressPoints} is
      *                                  not more than 1
      */
     private MultiPointToSinglePointIntent(ApplicationId appId,
-                                         Key key,
-                                         TrafficSelector selector,
-                                         TrafficTreatment treatment,
-                                         Set<ConnectPoint> ingressPoints,
-                                         ConnectPoint egressPoint,
-                                         List<Constraint> constraints,
-                                         int priority) {
+                                          Key key,
+                                          TrafficSelector selector,
+                                          TrafficTreatment treatment,
+                                          Set<ConnectPoint> ingressPoints,
+                                          ConnectPoint egressPoint,
+                                          List<Constraint> constraints,
+                                          int priority,
+                                          Map<ConnectPoint, TrafficSelector> ingressSelectors
+                                          ) {
         super(appId, key, Collections.emptyList(), selector, treatment, constraints,
                 priority);
 
@@ -76,6 +85,7 @@
 
         this.ingressPoints = Sets.newHashSet(ingressPoints);
         this.egressPoint = egressPoint;
+        this.ingressSelectors = ingressSelectors;
     }
 
     /**
@@ -85,6 +95,7 @@
         super();
         this.ingressPoints = null;
         this.egressPoint = null;
+        this.ingressSelectors = null;
     }
 
     /**
@@ -116,6 +127,7 @@
     public static final class Builder extends ConnectivityIntent.Builder {
         Set<ConnectPoint> ingressPoints;
         ConnectPoint egressPoint;
+        Map<ConnectPoint, TrafficSelector> ingressSelectors = Collections.emptyMap();
 
         private Builder() {
             // Hide constructor
@@ -189,13 +201,30 @@
         }
 
         /**
+         * Sets the selectors of the multi point to single point intent
+         * that will be built.
+         *
+         * @param ingressSelectors the multiple selectos
+         * @return this builder
+         */
+        public Builder selectors(Map<ConnectPoint, TrafficSelector> ingressSelectors) {
+            this.ingressSelectors = ImmutableMap.copyOf(ingressSelectors);
+            return this;
+        }
+
+        /**
          * Builds a multi point to single point intent from the
          * accumulated parameters.
          *
-         * @return point to point intent
+         * @return multi point to single point intent
          */
         public MultiPointToSinglePointIntent build() {
 
+            if (selector != null && !selector.criteria().isEmpty() &&
+                    ingressSelectors != null && !ingressSelectors.isEmpty()) {
+                throw new IllegalArgumentException("Selector and Multiple Selectors are both set");
+            }
+
             return new MultiPointToSinglePointIntent(
                     appId,
                     key,
@@ -204,7 +233,8 @@
                     ingressPoints,
                     egressPoint,
                     constraints,
-                    priority
+                    priority,
+                    ingressSelectors
             );
         }
     }
@@ -229,6 +259,14 @@
         return egressPoint;
     }
 
+    /**
+     * Returns the multiple selectors jointly with their connection points.
+     * @return multiple selectors
+     */
+    public Map<ConnectPoint, TrafficSelector> ingressSelectors() {
+        return ingressSelectors;
+    }
+
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
@@ -241,6 +279,7 @@
                 .add("treatment", treatment())
                 .add("ingress", ingressPoints())
                 .add("egress", egressPoint())
+                .add("selectors", ingressSelectors())
                 .add("constraints", constraints())
                 .toString();
     }