blob: 25b98a59406a36171f6d3def1dc09eb9605421c2 [file] [log] [blame]
Jonathan Hartaa380972014-04-03 10:24:46 -07001package net.onrc.onos.core.intent;
Toshio Koideb609b3b2014-02-14 18:25:52 -08002
3import java.util.Collection;
4import java.util.EventListener;
5import java.util.HashMap;
6import java.util.HashSet;
Toshio Koideb609b3b2014-02-14 18:25:52 -08007import java.util.LinkedList;
Toshio Koideb609b3b2014-02-14 18:25:52 -08008import java.util.Map.Entry;
9
Jonathan Hartaa380972014-04-03 10:24:46 -070010import net.onrc.onos.core.intent.Intent.IntentState;
11import net.onrc.onos.core.intent.runtime.IntentStateList;
Toshio Koideb609b3b2014-02-14 18:25:52 -080012
13/**
14 * @author Toshio Koide (t-koide@onlab.us)
15 */
16public class IntentMap {
Ray Milkey269ffb92014-04-03 14:43:30 -070017 private HashSet<ChangedListener> listeners = new HashSet<>();
18 private HashMap<String, Intent> intents = new HashMap<>();
19 private LinkedList<ChangedEvent> events = new LinkedList<>();
Toshio Koidedf2eab92014-02-20 11:24:59 -080020
Ray Milkey269ffb92014-04-03 14:43:30 -070021 public enum ChangedEventType {
22 /**
23 * Added new intent.
24 */
25 ADDED,
Toshio Koideb609b3b2014-02-14 18:25:52 -080026
Ray Milkey269ffb92014-04-03 14:43:30 -070027 /**
28 * Removed existing intent.
29 * The specified intent is an instance of Intent class (not a child class)
30 * Only id and state are valid.
31 */
32 REMOVED,
Toshio Koideb609b3b2014-02-14 18:25:52 -080033
Ray Milkey269ffb92014-04-03 14:43:30 -070034 /**
35 * Changed state of existing intent.
36 * The specified intent is an instance of Intent class (not a child class)
37 * Only id and state are valid.
38 */
39 STATE_CHANGED,
40 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080041
Pavlin Radoslavovfee80982014-04-10 12:12:04 -070042 public static class ChangedEvent {
Ray Milkey269ffb92014-04-03 14:43:30 -070043 public ChangedEvent(ChangedEventType eventType, Intent intent) {
44 this.eventType = eventType;
45 this.intent = intent;
46 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080047
Ray Milkey269ffb92014-04-03 14:43:30 -070048 public ChangedEventType eventType;
49 public Intent intent;
Pavlin Radoslavovb6309292014-04-11 03:25:47 -070050
51 /**
52 * Get a string representation of the object.
53 * <p/>
54 * The string has the following form:
55 * [eventType=XXX intent=XXX]
56 *
57 * @return a string representation of the object.
58 */
59 @Override
60 public String toString() {
61 StringBuilder ret = new StringBuilder();
62 ret.append("[eventType=");
63 ret.append(this.eventType.toString());
64 ret.append(" intent=");
65 ret.append(this.intent.toString());
66 ret.append("]");
67 return ret.toString();
68 }
Ray Milkey269ffb92014-04-03 14:43:30 -070069 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080070
Ray Milkey269ffb92014-04-03 14:43:30 -070071 public interface ChangedListener extends EventListener {
72 void intentsChange(LinkedList<ChangedEvent> events);
73 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080074
Ray Milkey269ffb92014-04-03 14:43:30 -070075 //================================================================================
76 // public methods
77 //================================================================================
Toshio Koideb609b3b2014-02-14 18:25:52 -080078
Ray Milkey269ffb92014-04-03 14:43:30 -070079 public void executeOperations(IntentOperationList operations) {
80 for (IntentOperation operation : operations) {
81 switch (operation.operator) {
82 case ADD:
83 handleAddOperation(operation);
84 break;
85 case REMOVE:
86 handleRemoveOperation(operation);
87 break;
88 case ERROR:
89 handleErrorOperation(operation);
90 break;
91 }
92 }
93 notifyEvents();
94 }
Toshio Koidedf2eab92014-02-20 11:24:59 -080095
Ray Milkey269ffb92014-04-03 14:43:30 -070096 public void purge() {
97 LinkedList<String> removeIds = new LinkedList<>();
98 for (Entry<String, Intent> entry : intents.entrySet()) {
99 Intent intent = entry.getValue();
100 if (intent.getState() == IntentState.DEL_ACK
101 || intent.getState() == IntentState.INST_NACK) {
102 removeIds.add(intent.getId());
103 }
104 }
105 for (String intentId : removeIds) {
106 removeIntent(intentId);
107 }
108 notifyEvents();
109 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800110
Ray Milkey269ffb92014-04-03 14:43:30 -0700111 public void changeStates(IntentStateList states) {
112 for (Entry<String, IntentState> state : states.entrySet()) {
113 setState(state.getKey(), state.getValue());
114 }
115 notifyEvents();
116 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800117
Ray Milkey269ffb92014-04-03 14:43:30 -0700118 public Intent getIntent(String intentId) {
119 return intents.get(intentId);
120 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800121
Ray Milkey269ffb92014-04-03 14:43:30 -0700122 public Collection<Intent> getAllIntents() {
123 return intents.values();
124 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800125
Ray Milkey269ffb92014-04-03 14:43:30 -0700126 public void addChangeListener(ChangedListener listener) {
127 listeners.add(listener);
128 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800129
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 public void removeChangedListener(ChangedListener listener) {
131 listeners.remove(listener);
132 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800133
Ray Milkey269ffb92014-04-03 14:43:30 -0700134 //================================================================================
135 // methods that affect intents map (protected)
136 //================================================================================
Toshio Koidedf2eab92014-02-20 11:24:59 -0800137
Ray Milkey269ffb92014-04-03 14:43:30 -0700138 protected void putIntent(Intent intent) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700139 if (intents.containsKey(intent.getId())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700140 removeIntent(intent.getId());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700141 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700142 intents.put(intent.getId(), intent);
143 events.add(new ChangedEvent(ChangedEventType.ADDED, intent));
144 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800145
Ray Milkey269ffb92014-04-03 14:43:30 -0700146 protected void removeIntent(String intentId) {
147 Intent intent = intents.remove(intentId);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700148 if (intent == null) {
149 return;
150 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700151 events.add(new ChangedEvent(ChangedEventType.REMOVED, intent));
152 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800153
Ray Milkey269ffb92014-04-03 14:43:30 -0700154 protected void setState(String intentId, IntentState state) {
155 Intent intent = intents.get(intentId);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700156 if (intent == null) {
157 return;
158 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700159 intent.setState(state);
160 events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED, intent));
161 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800162
Ray Milkey269ffb92014-04-03 14:43:30 -0700163 //================================================================================
164 // helper methods (protected)
165 //================================================================================
Toshio Koidedf2eab92014-02-20 11:24:59 -0800166
Ray Milkey269ffb92014-04-03 14:43:30 -0700167 protected void handleAddOperation(IntentOperation operation) {
168 putIntent(operation.intent);
169 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800170
Ray Milkey269ffb92014-04-03 14:43:30 -0700171 protected void handleRemoveOperation(IntentOperation operation) {
172 Intent intent = getIntent(operation.intent.getId());
173 if (intent == null) {
174 // TODO error handling
Ray Milkey1aa71f82014-04-08 16:23:24 -0700175 return;
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 } else {
177 setState(intent.getId(), IntentState.DEL_REQ);
178 }
179 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800180
Ray Milkey269ffb92014-04-03 14:43:30 -0700181 protected void handleErrorOperation(IntentOperation operation) {
182 //TODO put error message into the intent
Toshio Koidedf2eab92014-02-20 11:24:59 -0800183
Ray Milkey269ffb92014-04-03 14:43:30 -0700184 ErrorIntent errorIntent = (ErrorIntent) operation.intent;
185 Intent targetIntent = intents.get(errorIntent.getId());
186 if (targetIntent == null) {
187 // TODO error handling
188 return;
189 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800190
Ray Milkey269ffb92014-04-03 14:43:30 -0700191 switch (targetIntent.getState()) {
192 case CREATED:
193 case INST_REQ:
194 case INST_ACK:
195 case REROUTE_REQ:
196 setState(targetIntent.getId(), IntentState.INST_NACK);
197 break;
198 case DEL_REQ:
199 setState(targetIntent.getId(), IntentState.DEL_PENDING);
200 break;
201 case INST_NACK:
202 case DEL_PENDING:
203 case DEL_ACK:
204 // do nothing
205 break;
206 }
207 }
208
209 protected void notifyEvents() {
210 for (ChangedListener listener : listeners) {
211 listener.intentsChange(events);
212 }
213 events.clear();
214 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800215}