Implement IntentMap and IntentOperation

Change-Id: I8ef5ddb37ae2694a984c190465e86026fa643e7b
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index a31cbde..de960f0 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -3,12 +3,19 @@
 /**
  * @author Toshio Koide (t-koide@onlab.us)
  */
-public abstract class Intent {
+public class Intent {	
 	enum IntentState {
-		// TODO;
+		CREATED,
+		INST_REQ,
+		INST_NACK,
+		INST_ACK,
+		DEL_REQ,
+		DEL_PENDING,
+		DEL_ACK,
 	}
+
 	protected String id;
-	protected IntentState state;
+	protected IntentState state = IntentState.CREATED;
 
 	/**
 	 * Default constructor for Kryo deserialization
@@ -20,20 +27,25 @@
 		this.id = id;
 	}
 
+	public Intent(String id, IntentState state) {
+		this.id = id;
+		this.state = state;
+	}
+
 	public String getId() {
 		return id;
 	}
-	
+
 	public IntentState getState() {
 		return state;
 	}
-	
+
 	public IntentState setState(IntentState newState) {
 		IntentState oldState = state;
 		state = newState;
 		return oldState;
 	}
-
+	
 	@Override
 	public int hashCode() {
 		return id.hashCode();
diff --git a/src/main/java/net/onrc/onos/intent/IntentMap.java b/src/main/java/net/onrc/onos/intent/IntentMap.java
new file mode 100644
index 0000000..f9d8b9f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/IntentMap.java
@@ -0,0 +1,109 @@
+package net.onrc.onos.intent;
+
+import java.util.Collection;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import net.onrc.onos.intent.Intent.IntentState;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentMap {
+	public enum ChangedEventType {
+		/**
+		 * Added new intent.
+		 */
+		ADDED,
+
+		/**
+		 * Removed existing intent.
+		 * The specified intent is an instance of Intent class (not a child class)
+		 * Only id and state are valid.
+		 */
+		REMOVED,
+
+		/**
+		 * Changed state of existing intent.
+		 * The specified intent is an instance of Intent class (not a child class)
+		 * Only id and state are valid.
+		 */
+		STATE_CHANGED,
+	}
+
+	public class ChangedEvent {
+		public ChangedEvent(ChangedEventType eventType, Intent intent) {
+			this.eventType = eventType;
+			this.intent = intent;
+		}
+		public ChangedEventType eventType;
+		public Intent intent;
+	}
+
+	public interface ChangedListener extends EventListener {
+		void intentsChange(LinkedList<ChangedEvent> events);
+	}
+
+	private HashSet<ChangedListener> listeners = new HashSet<>();
+	protected HashMap<String, Intent> intents = new HashMap<>();
+
+	public void executeOperations(List<IntentOperation> operations) {
+		LinkedList<ChangedEvent> events = new LinkedList<>();
+		for (IntentOperation operation: operations) {
+			switch (operation.operator) {
+			case ADD:
+				intents.put(operation.intent.getId(), operation.intent);
+				events.add(new ChangedEvent(ChangedEventType.ADDED, operation.intent));
+				break;
+			case REMOVE:
+				Intent intent = intents.get(operation.intent.getId());
+				if (intent == null) {
+					// TODO throw exception
+				}
+				else {
+					intent.setState(Intent.IntentState.DEL_REQ);
+					events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED,
+							new Intent(intent.getId(), Intent.IntentState.DEL_REQ)));
+				}
+				break;
+			}
+		}
+		for (ChangedListener listener: listeners) {
+			listener.intentsChange(events);
+		}
+	}
+
+	public void purge() {
+		Iterator<Entry<String, Intent>> i = intents.entrySet().iterator();
+		while (i.hasNext()) {
+			Entry<String, Intent> entry = i.next();
+			Intent intent = entry.getValue();
+			if (intent.getState() == IntentState.DEL_ACK
+					|| intent.getState() == IntentState.INST_NACK) {
+				i.remove();
+			}
+		}
+	}
+
+	public Collection<Intent> getAllIntents() {
+		return intents.values();
+	}
+
+	public Intent getIntent(String key) {
+		return intents.get(key);
+	}
+
+
+	public void addChangeListener(ChangedListener listener) {
+		listeners.add(listener);
+	}
+
+	public void removeChangedListener(ChangedListener listener) {
+		listeners.remove(listener);
+	}
+}
diff --git a/src/main/java/net/onrc/onos/intent/IntentOperation.java b/src/main/java/net/onrc/onos/intent/IntentOperation.java
new file mode 100644
index 0000000..8ac45c9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/IntentOperation.java
@@ -0,0 +1,29 @@
+package net.onrc.onos.intent;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentOperation {
+	public enum Operator {
+		/**
+		 * Add new intent specified by intent field
+		 */
+		ADD,
+
+		/**
+		 * Remove existing intent specified by intent field.
+		 * The specified intent should be an instance of Intent class (not a child class)
+		 */
+		REMOVE,
+	}
+
+	public IntentOperation() {}
+
+	public IntentOperation(Operator operator, Intent intent) {
+		this.operator = operator;
+		this.intent = intent;
+	}
+
+	public Operator operator;
+	public Intent intent;
+}