Intent installer and operations for domain intents.

Change-Id: Id4597baebf587b1bc9b3ae9013383ae50472fa4c
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
index 0334bba..3ce320d 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
@@ -28,6 +28,10 @@
 import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription;
 import org.onosproject.net.behaviour.protection.ProtectionConfig;
 import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.domain.DomainIntent;
+import org.onosproject.net.domain.DomainIntentOperations;
+import org.onosproject.net.domain.DomainIntentOperationsContext;
+import org.onosproject.net.domain.DomainIntentService;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.flow.FlowRuleOperationsContext;
@@ -80,6 +84,7 @@
     private FlowRuleService flowRuleService;
     private FlowObjectiveService flowObjectiveService;
     private NetworkConfigService networkConfigService;
+    private DomainIntentService domainIntentService;
 
     private enum Direction {
         ADD,
@@ -94,16 +99,19 @@
      * @param flowRuleService      flow rule service
      * @param flowObjectiveService flow objective service
      * @param networkConfigService network configuration service
+     * @param domainIntentService  domain intent service
      */
     void init(IntentStore intentStore, ObjectiveTrackerService trackerService,
               FlowRuleService flowRuleService, FlowObjectiveService flowObjectiveService,
-              NetworkConfigService networkConfigService) {
+              NetworkConfigService networkConfigService, DomainIntentService domainIntentService) {
+
         this.store = intentStore;
         this.trackerService = trackerService;
         //TODO Various services should be plugged to the intent installer instead of being hardcoded
         this.flowRuleService = flowRuleService;
         this.flowObjectiveService = flowObjectiveService;
         this.networkConfigService = networkConfigService;
+        this.domainIntentService = domainIntentService;
     }
 
     // FIXME: Intent Manager should have never become dependent on a specific intent type(s).
@@ -230,7 +238,7 @@
         }
     }
 
-    // --- Utilities to support various installable Intent ----
+    // --- Utilities to support FlowRule vs. FlowObjective vs. DomainIntent behavior ----
 
     // Creates the set of contexts appropriate for tracking operations of the
     // the specified intents.
@@ -248,6 +256,9 @@
         if (isInstallable(toUninstall, toInstall, ProtectionEndpointIntent.class)) {
             contexts.add(new ProtectionConfigOperationContext(intentContext));
         }
+        if (isInstallable(toUninstall, toInstall, DomainIntent.class)) {
+            contexts.add(new DomainIntentOperationContext(intentContext));
+        }
 
         if (contexts.isEmpty()) {
             log.warn("{} did not contain installable Intents", intentContext);
@@ -457,7 +468,8 @@
         private boolean isSupported(Intent intent) {
             return intent instanceof FlowRuleIntent ||
                    intent instanceof FlowObjectiveIntent ||
-                   intent instanceof ProtectionEndpointIntent;
+                   intent instanceof ProtectionEndpointIntent ||
+                   intent instanceof DomainIntent;
         }
 
         protected ToStringHelper toStringHelper() {
@@ -850,6 +862,59 @@
         }
     }
 
+    // Context for applying and tracking operations related to domain intents.
+    private class DomainIntentOperationContext extends OperationContext {
+        DomainIntentOperations.Builder builder = DomainIntentOperations.builder();
+        DomainIntentOperationsContext domainOperationsContext;
+
+        DomainIntentOperationContext(IntentInstallationContext context) {
+            super(context);
+        }
+        @Override
+        void apply() {
+            domainOperationsContext = new DomainIntentOperationsContext() {
+                @Override
+                public void onSuccess(DomainIntentOperations ops) {
+                    successConsumer.accept(DomainIntentOperationContext.this);
+                }
+
+                @Override
+                public void onError(DomainIntentOperations ops) {
+                    errorConsumer.accept(DomainIntentOperationContext.this);
+                }
+            };
+            DomainIntentOperations operations = builder.build(domainOperationsContext);
+
+            if (log.isTraceEnabled()) {
+                log.trace("submitting domain intent {} -> {}",
+                          toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
+                          toInstall.map(x -> x.key().toString()).orElse("<empty>"));
+            }
+            domainIntentService.sumbit(operations);
+        }
+
+        @Override
+        public void prepareIntents(List<Intent> intentsToApply, Direction direction) {
+            List<DomainIntent> intents = intentsToApply.stream()
+                    .filter(x -> x instanceof DomainIntent)
+                    .map(x -> (DomainIntent) x)
+                    .collect(Collectors.toList());
+
+            for (DomainIntent intent : intents) {
+                if (direction == Direction.ADD) {
+                    builder.add(intent);
+                } else {
+                    builder.remove(intent);
+                }
+            }
+        }
+
+        @Override
+        public Object error() {
+            return domainOperationsContext;
+        }
+    }
+
     private class ErrorContext extends OperationContext {
         ErrorContext(IntentInstallationContext context) {
             super(context);
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 353af4d..3b542bd 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -30,6 +30,7 @@
 import org.onosproject.event.AbstractListenerManager;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.domain.DomainIntentService;
 import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
 import org.onosproject.net.group.GroupKey;
@@ -126,6 +127,9 @@
     protected FlowObjectiveService flowObjectiveService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DomainIntentService domainIntentService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ResourceService resourceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -157,7 +161,7 @@
         configService.registerProperties(getClass());
 
         intentInstaller.init(store, trackerService, flowRuleService, flowObjectiveService,
-                             networkConfigService);
+                             networkConfigService, domainIntentService);
         if (skipReleaseResourcesOnWithdrawal) {
             store.setDelegate(testOnlyDelegate);
         } else {
@@ -175,7 +179,7 @@
 
     @Deactivate
     public void deactivate() {
-        intentInstaller.init(null, null, null, null, null);
+        intentInstaller.init(null, null, null, null, null, null);
         if (skipReleaseResourcesOnWithdrawal) {
             store.unsetDelegate(testOnlyDelegate);
         } else {