Support for OTN using optical circuit intents.
Refined DeviceResourceService.

Change-Id: I489f368a0fac5f4a8d0a1a1cb716f845558db35e
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentDeviceResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentDeviceResourceStore.java
index bfdc536..519fc83 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentDeviceResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentDeviceResourceStore.java
@@ -35,6 +35,7 @@
 import org.onosproject.store.service.TransactionalMap;
 import org.slf4j.Logger;
 
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -52,12 +53,14 @@
 
     private static final String PORT_ALLOCATIONS = "PortAllocations";
     private static final String INTENT_ALLOCATIONS = "IntentAllocations";
+    private static final String INTENT_MAPPING = "IntentMapping";
 
     private static final Serializer SERIALIZER = Serializer.using(
             new KryoNamespace.Builder().register(KryoNamespaces.API).build());
 
     private ConsistentMap<Port, IntentId> portAllocMap;
     private ConsistentMap<IntentId, Set<Port>> intentAllocMap;
+    private ConsistentMap<IntentId, Set<IntentId>> intentMapping;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
@@ -75,6 +78,10 @@
                 .withName(INTENT_ALLOCATIONS)
                 .withSerializer(SERIALIZER)
                 .build();
+        intentMapping = storageService.<IntentId, Set<IntentId>>consistentMapBuilder()
+                .withName(INTENT_MAPPING)
+                .withSerializer(SERIALIZER)
+                .build();
         log.info("Started");
     }
 
@@ -110,7 +117,7 @@
     }
 
     @Override
-    public void allocatePorts(Set<Port> ports, IntentId intentId) {
+    public boolean allocatePorts(Set<Port> ports, IntentId intentId) {
         checkNotNull(ports);
         checkArgument(ports.size() > 0);
         checkNotNull(intentId);
@@ -120,20 +127,78 @@
         try {
             TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
             for (Port port : ports) {
-                portAllocs.put(port, intentId);
+                if (portAllocs.putIfAbsent(port, intentId) != null) {
+                    throw new Exception("Port already allocated " + port.toString());
+                }
             }
+
             TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
             intentAllocs.put(intentId, ports);
             tx.commit();
         } catch (Exception e) {
             log.error("Exception thrown, rolling back", e);
             tx.abort();
-            throw e;
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public Set<Port> getAllocations(IntentId intentId) {
+        if (!intentAllocMap.containsKey(intentId)) {
+            Collections.emptySet();
+        }
+
+        return intentAllocMap.get(intentId).value();
+    }
+
+    @Override
+    public IntentId getAllocations(Port port) {
+        if (!portAllocMap.containsKey(port)) {
+            return null;
+        }
+
+        return portAllocMap.get(port).value();
+    }
+
+    @Override
+    public Set<IntentId> getMapping(IntentId intentId) {
+        return intentMapping.get(intentId).value();
+    }
+
+    @Override
+    public void releaseMapping(IntentId keyIntentId, IntentId valIntentId) {
+        if (!intentMapping.containsKey(keyIntentId)) {
+            return;
+        }
+
+        Set<IntentId> intents = intentMapping.get(keyIntentId).value();
+
+        try {
+            intents.remove(valIntentId);
+        } catch (Exception e) {
+            log.error("Trying to remove non-existing mapping {} {}", keyIntentId, valIntentId);
         }
     }
 
     @Override
-    public void releasePorts(IntentId intentId) {
+    public boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId) {
+        Set<IntentId> intents = intentMapping.get(keyIntentId).value();
+
+        if (intents == null) {
+            intents = Collections.singleton(valIntentId);
+        } else {
+            intents.add(valIntentId);
+        }
+
+        intentMapping.put(keyIntentId, intents);
+
+        return true;
+    }
+
+    @Override
+    public boolean releasePorts(IntentId intentId) {
         checkNotNull(intentId);
 
         TransactionContext tx = getTxContext();
@@ -150,7 +215,9 @@
         } catch (Exception e) {
             log.error("Exception thrown, rolling back", e);
             tx.abort();
-            throw e;
+            return false;
         }
+
+        return true;
     }
 }
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index b3e7a75..00fa550 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -136,6 +136,7 @@
 import org.onosproject.net.intent.MplsIntent;
 import org.onosproject.net.intent.MplsPathIntent;
 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+import org.onosproject.net.intent.OpticalCircuitIntent;
 import org.onosproject.net.intent.OpticalConnectivityIntent;
 import org.onosproject.net.intent.OpticalPathIntent;
 import org.onosproject.net.intent.PathIntent;
@@ -361,6 +362,7 @@
                     LinkCollectionIntent.class,
                     OpticalConnectivityIntent.class,
                     OpticalPathIntent.class,
+                    OpticalCircuitIntent.class,
                     LinkResourceRequest.class,
                     DefaultLinkResourceRequest.class,
                     BandwidthResourceRequest.class,