Move adsal into its own subdirectory.
[controller.git] / opendaylight / adsal / forwardingrulesmanager / api / src / main / java / org / opendaylight / controller / forwardingrulesmanager / FlowEntry.java
diff --git a/opendaylight/adsal/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java b/opendaylight/adsal/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java
new file mode 100644 (file)
index 0000000..d9a0891
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwardingrulesmanager;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.match.Match;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents a flow applications request Forwarding Rules Manager to install on
+ * a network node. A FlowEntry is constituted of a flow (match + actions), the
+ * target network node, and the flow name. It also includes a group name. For
+ * instance the flows constituting a policy all share the same group name.
+ */
+public class FlowEntry implements Cloneable, Serializable {
+    protected static final Logger logger = LoggerFactory.getLogger(FlowEntry.class);
+    private static final long serialVersionUID = 1L;
+    private static final Logger log = LoggerFactory.getLogger(FlowEntry.class);
+    private String groupName; // group name
+    private String flowName; // flow name (may be null)
+    private Node node; // network node where to install the flow
+    private Flow flow; // match + action
+
+    public FlowEntry(String groupName, String flowName, Flow flow, Node node) {
+        this.groupName = groupName;
+        this.flow = flow;
+        this.node = node;
+        this.flowName = (flowName != null) ? flowName : constructFlowName();
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String name) {
+        this.groupName = name;
+    }
+
+    /**
+     * Return the actual Flow contained in this entry
+     *
+     * @return the flow
+     */
+    public Flow getFlow() {
+        return flow;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+
+    public void setNode(Node n) {
+        this.node = n;
+    }
+
+    public String getFlowName() {
+        return flowName;
+    }
+
+    public void setFlowName(String n) {
+        this.flowName = n;
+    }
+
+    @Override
+    public FlowEntry clone() {
+        FlowEntry cloned = null;
+        try {
+            cloned = (FlowEntry) super.clone();
+            cloned.flow = this.flow.clone();
+        } catch (CloneNotSupportedException e) {
+            log.warn("exception in clone", e);
+        }
+        return cloned;
+    }
+
+    /*
+     * Only accounts fields which uniquely identify a flow for collision
+     * purposes: node, match and priority
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((node == null) ? 0 : node.hashCode());
+        result = prime * result + ((flow == null) ? 0 : (int) flow.getPriority());
+        result = prime * result + ((flow == null || flow.getMatch() == null) ? 0 : flow.getMatch().hashCode());
+
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        FlowEntry other = (FlowEntry) obj;
+
+        if (node == null) {
+            if (other.node != null) {
+                return false;
+            }
+        } else if (!node.equals(other.node)) {
+            return false;
+        }
+
+        if (flow == null) {
+            return other.flow == null;
+        } else if (other.flow == null) {
+            return false;
+        }
+        if (flow.getPriority() != other.flow.getPriority()) {
+            return false;
+        }
+        if (flow.getMatch() == null) {
+            if (other.flow.getMatch() != null) {
+                return false;
+            }
+        } else if (!flow.getMatch().equals(other.flow.getMatch())) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "FlowEntry[flowName = " + flowName + ", groupName = " + groupName + ", node = " + node + ", flow = "
+                + flow + "]";
+    }
+
+    private String constructFlowName() {
+        return this.groupName + "_" + new Date().toString();
+    }
+
+    public boolean equalsByNodeAndName(Node node, String flowName) {
+        return this.node.equals(node) && this.flowName.equals(flowName);
+    }
+
+    /**
+     * Merges the current Flow with the passed Container Flow
+     *
+     * Note: Container Flow merging is not an injective function. Be m1 and m2
+     * two different matches, and be f() the flow merge function, such that y1 =
+     * f(m1) and y2 = f(m2) are the two merged matches, we may have: y1 = y2
+     *
+     *
+     * @param containerFlow
+     * @return this merged FlowEntry
+     */
+    public FlowEntry mergeWith(ContainerFlow containerFlow) {
+        Match myMatch = flow.getMatch();
+
+        Match filter = containerFlow.getMatch();
+
+        // Merge
+        Match merge = myMatch.mergeWithFilter(filter);
+
+        // Replace this Flow's match with merged version
+        flow.setMatch(merge);
+
+        return this;
+    }
+
+    /**
+     * Returns whether this entry is the result of an internal generated static
+     * flow
+     *
+     * @return true if internal generated static flow, false otherwise
+     */
+    public boolean isInternal() {
+        return flowName.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN)
+                && flowName.endsWith(FlowConfig.INTERNALSTATICFLOWEND);
+    }
+}