--- /dev/null
+package org.openflow.protocol.action;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+import org.openflow.util.U16;
+
+/**
+ * The base class for all OpenFlow Actions.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFAction implements Cloneable, Serializable{
+ /**
+ * Note the true minimum length for this header is 8 including a pad to 64
+ * bit alignment, however as this base class is used for demuxing an
+ * incoming Action, it is only necessary to read the first 4 bytes. All
+ * Actions extending this class are responsible for reading/writing the
+ * first 8 bytes, including the pad if necessary.
+ */
+ public static int MINIMUM_LENGTH = 4;
+ public static int OFFSET_LENGTH = 2;
+ public static int OFFSET_TYPE = 0;
+
+ protected OFActionType type;
+ protected short length;
+
+ /**
+ * Get the length of this message
+ *
+ * @return
+ */
+ public short getLength() {
+ return length;
+ }
+
+ /**
+ * Get the length of this message, unsigned
+ *
+ * @return
+ */
+ public int getLengthU() {
+ return U16.f(length);
+ }
+
+ /**
+ * Set the length of this message
+ *
+ * @param length
+ */
+ public OFAction setLength(short length) {
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Get the type of this message
+ *
+ * @return OFActionType enum
+ */
+ public OFActionType getType() {
+ return this.type;
+ }
+
+ /**
+ * Set the type of this message
+ *
+ * @param type
+ */
+ public void setType(OFActionType type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns a summary of the message
+ * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
+ */
+ public String toString() {
+ return "ofaction" +
+ ";t=" + this.getType() +
+ ";l=" + this.getLength();
+ }
+
+ /**
+ * Given the output from toString(),
+ * create a new OFAction
+ * @param val
+ * @return
+ */
+ public static OFAction fromString(String val) {
+ String tokens[] = val.split(";");
+ if (!tokens[0].equals("ofaction"))
+ throw new IllegalArgumentException("expected 'ofaction' but got '" +
+ tokens[0] + "'");
+ String type_tokens[] = tokens[1].split("=");
+ String len_tokens[] = tokens[2].split("=");
+ OFAction action = new OFAction();
+ action.setLength(Short.valueOf(len_tokens[1]));
+ action.setType(OFActionType.valueOf(type_tokens[1]));
+ return action;
+ }
+
+ public void readFrom(ByteBuffer data) {
+ this.type = OFActionType.valueOf(data.getShort());
+ this.length = data.getShort();
+ // Note missing PAD, see MINIMUM_LENGTH comment for details
+ }
+
+ public void writeTo(ByteBuffer data) {
+ data.putShort(type.getTypeValue());
+ data.putShort(length);
+ // Note missing PAD, see MINIMUM_LENGTH comment for details
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 347;
+ int result = 1;
+ result = prime * result + length;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFAction)) {
+ return false;
+ }
+ OFAction other = (OFAction) obj;
+ if (length != other.length) {
+ return false;
+ }
+ if (type == null) {
+ if (other.type != null) {
+ return false;
+ }
+ } else if (!type.equals(other.type)) {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public OFAction clone() throws CloneNotSupportedException {
+ return (OFAction) super.clone();
+ }
+
+}