Refactored cross connect helpers to optical drivers package.

Change-Id: Iae23025cf0b33c51123911f3ff1249cabc812be2
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnect.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnect.java
new file mode 100644
index 0000000..b1131ac
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnect.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.optical.flowrule;
+
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
+
+/**
+ * Interface for cross connects as common in optical networking.
+ */
+public interface CrossConnect extends FlowRule {
+    /**
+     * Returns the add/drop port of the cross connect.
+     *
+     * @return port number
+     */
+    PortNumber addDrop();
+
+    /**
+     * Returns the wavelength of the cross connect.
+     *
+     * @return OCh signal
+     */
+    OchSignal ochSignal();
+
+    /**
+     * Returns true if cross connect is adding traffic.
+     *
+     * @return true if add rule, false if drop rule
+     */
+    boolean isAddRule();
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectCache.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectCache.java
new file mode 100644
index 0000000..ff16376
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectCache.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.optical.flowrule;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.net.flow.FlowId;
+
+/**
+ * Simple interface to cache flow ID and priority of cross connect flows.
+ */
+public interface CrossConnectCache {
+    /**
+     * Returns the flow ID and priority corresponding to the flow hash.
+     *
+     * @param hash flow hash
+     * @return flow ID and priority, null if not in cache
+     */
+    Pair<FlowId, Integer> get(int hash);
+
+    /**
+     * Stores the flow ID and priority corresponding to the flow hash.
+     *
+     * @param hash flow hash
+     * @param flowId flow ID
+     * @param priority flow priority
+     */
+    void set(int hash, FlowId flowId, int priority);
+
+    /**
+     * Removes the given hash from the cache.
+     *
+     * @param hash flow hash
+     */
+    void remove(int hash);
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectFlowRule.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectFlowRule.java
new file mode 100644
index 0000000..7b0579f
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/CrossConnectFlowRule.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.optical.flowrule;
+
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Cross connect abstraction based on a flow rule.
+ */
+public class CrossConnectFlowRule extends DefaultFlowRule implements CrossConnect {
+    private PortNumber addDrop;
+    private OchSignal ochSignal;
+    private boolean isAddRule;
+
+    public CrossConnectFlowRule(FlowRule rule, List<PortNumber> linePorts) {
+        super(rule);
+
+        Set<Criterion> criteria = rule.selector().criteria();
+        List<Instruction> instructions = rule.treatment().immediate();
+
+        // Proper cross connect has criteria for input port, OChSignal and OCh signal type.
+        // Instruction must be output to port.
+        checkArgument(criteria.size() == 3, "Wrong size of flow rule criteria for cross connect.");
+        checkArgument(instructions.size() == 1, "Wrong size of flow rule instructions for cross connect.");
+        // FIXME: Ensure criteria has exactly one of each match type
+        criteria.forEach(
+                c -> checkArgument(c instanceof OchSignalCriterion ||
+                        c instanceof OchSignalTypeCriterion ||
+                        c instanceof PortCriterion,
+                        "Incompatible flow rule criteria for cross connect: " + criteria
+                )
+        );
+        checkArgument(instructions.get(0).type() == Instruction.Type.OUTPUT,
+                "Incompatible flow rule instructions for cross connect: " + instructions);
+
+        ochSignal = criteria.stream()
+                .filter(c -> c instanceof OchSignalCriterion)
+                .map(c -> ((OchSignalCriterion) c).lambda())
+                .findAny()
+                .orElse(null);
+
+        // Add or drop rule?
+        Instructions.OutputInstruction outInstruction = (Instructions.OutputInstruction) instructions.get(0);
+        if (linePorts.contains(outInstruction.port())) {
+            addDrop = criteria.stream()
+                    .filter(c -> c instanceof PortCriterion)
+                    .map(c -> ((PortCriterion) c).port())
+                    .findAny()
+                    .orElse(null);
+            isAddRule = true;
+        } else {
+            addDrop = outInstruction.port();
+            isAddRule = false;
+        }
+    }
+
+    @Override
+    public PortNumber addDrop() {
+        return addDrop;
+    }
+
+    @Override
+    public OchSignal ochSignal() {
+        return ochSignal;
+    }
+
+    @Override
+    public boolean isAddRule() {
+        return isAddRule;
+    }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/DefaultCrossConnectCache.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/DefaultCrossConnectCache.java
new file mode 100644
index 0000000..1a73698
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/DefaultCrossConnectCache.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.driver.optical.flowrule;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.flow.FlowId;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Simple implementation of a local flow rule cache that stores the flow ID and priority.
+ *
+ * Use this if you have a device that does not allow you to store these fields.
+ *
+ * WARNING: Be aware that this implementation makes no attempt to use a distributed store
+ * for the cache, so do not rely on it to support fail-over in multi-instance deployments.
+ * If the instance which holds the cache goes down, you *will* be in trouble.
+ */
+@Component(immediate = true, enabled = true)
+@Service
+public class DefaultCrossConnectCache implements CrossConnectCache {
+    private final Map<Integer, Pair<FlowId, Integer>> cache = new HashMap<>();
+
+    @Override
+    public Pair<FlowId, Integer> get(int hash) {
+        return cache.get(hash);
+    }
+
+    @Override
+    public void set(int hash, FlowId flowId, int priority) {
+        cache.put(hash, Pair.of(flowId, priority));
+    }
+
+    @Override
+    public void remove(int hash) {
+        cache.remove(hash);
+    }
+}
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/package-info.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/package-info.java
new file mode 100644
index 0000000..6e3e8e0
--- /dev/null
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/flowrule/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementations of the {@link org.onosproject.net.flow.FlowRuleProgrammable} behaviour for optical devices.
+ */
+package org.onosproject.driver.optical.flowrule;
\ No newline at end of file
diff --git a/drivers/optical/src/main/java/org/onosproject/driver/optical/query/LincOELambdaQuery.java b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/LincOELambdaQuery.java
index 9f7bada..d7fc40a 100644
--- a/drivers/optical/src/main/java/org/onosproject/driver/optical/query/LincOELambdaQuery.java
+++ b/drivers/optical/src/main/java/org/onosproject/driver/optical/query/LincOELambdaQuery.java
@@ -47,7 +47,7 @@
      * OMS ports expose 80 fixed grid lambdas of 50GHz width,
      * centered around the ITU-T center frequency 193.1 THz.
      */
-    private static final Set<OchSignal> OMS_LAMDAS = IntStream.range(0, LAMBDA_COUNT)
+    private static final Set<OchSignal> OMS_LAMBDAS = IntStream.range(0, LAMBDA_COUNT)
             .mapToObj(x -> new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, x - (LAMBDA_COUNT / 2), 4))
             .collect(GuavaCollectors.toImmutableSet());
 
@@ -63,6 +63,6 @@
             return ImmutableSet.of();
         }
 
-        return OMS_LAMDAS;
+        return OMS_LAMBDAS;
     }
 }