blob: ae314a72fa962deababe59d59822c202dfead28f [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 {
Toshio Koidedf2eab92014-02-20 11:24:59 -080017 private HashSet<ChangedListener> listeners = new HashSet<>();
18 private HashMap<String, Intent> intents = new HashMap<>();
19 private LinkedList<ChangedEvent> events = new LinkedList<>();
20
Toshio Koideb609b3b2014-02-14 18:25:52 -080021 public enum ChangedEventType {
22 /**
23 * Added new intent.
24 */
25 ADDED,
26
27 /**
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,
33
34 /**
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 }
41
42 public class ChangedEvent {
43 public ChangedEvent(ChangedEventType eventType, Intent intent) {
44 this.eventType = eventType;
45 this.intent = intent;
46 }
47 public ChangedEventType eventType;
48 public Intent intent;
49 }
50
51 public interface ChangedListener extends EventListener {
52 void intentsChange(LinkedList<ChangedEvent> events);
53 }
54
Toshio Koidedf2eab92014-02-20 11:24:59 -080055 //================================================================================
56 // public methods
57 //================================================================================
Toshio Koideb609b3b2014-02-14 18:25:52 -080058
Toshio Koide4f308732014-02-18 15:19:48 -080059 public void executeOperations(IntentOperationList operations) {
Toshio Koideb609b3b2014-02-14 18:25:52 -080060 for (IntentOperation operation: operations) {
61 switch (operation.operator) {
62 case ADD:
Toshio Koidedf2eab92014-02-20 11:24:59 -080063 handleAddOperation(operation);
Toshio Koideb609b3b2014-02-14 18:25:52 -080064 break;
65 case REMOVE:
Toshio Koidedf2eab92014-02-20 11:24:59 -080066 handleRemoveOperation(operation);
67 break;
68 case ERROR:
69 handleErrorOperation(operation);
Toshio Koideb609b3b2014-02-14 18:25:52 -080070 break;
71 }
72 }
Toshio Koidedf2eab92014-02-20 11:24:59 -080073 notifyEvents();
Toshio Koideb609b3b2014-02-14 18:25:52 -080074 }
75
76 public void purge() {
Toshio Koide0c9106d2014-02-19 15:26:38 -080077 LinkedList<String> removeIds = new LinkedList<>();
78 for (Entry<String, Intent> entry: intents.entrySet()) {
Toshio Koideb609b3b2014-02-14 18:25:52 -080079 Intent intent = entry.getValue();
80 if (intent.getState() == IntentState.DEL_ACK
81 || intent.getState() == IntentState.INST_NACK) {
Toshio Koide0c9106d2014-02-19 15:26:38 -080082 removeIds.add(intent.getId());
Toshio Koidedf2eab92014-02-20 11:24:59 -080083 }
Toshio Koide0c9106d2014-02-19 15:26:38 -080084 }
85 for (String intentId: removeIds) {
86 removeIntent(intentId);
Toshio Koideb609b3b2014-02-14 18:25:52 -080087 }
Toshio Koidedf2eab92014-02-20 11:24:59 -080088 notifyEvents();
89 }
90
Toshio Koide066506e2014-02-20 19:52:09 -080091 public void changeStates(IntentStateList states) {
Toshio Koidedf2eab92014-02-20 11:24:59 -080092 for (Entry<String, IntentState> state: states.entrySet()) {
93 setState(state.getKey(), state.getValue());
94 }
95 notifyEvents();
96 }
97
98 public Intent getIntent(String intentId) {
99 return intents.get(intentId);
Toshio Koideb609b3b2014-02-14 18:25:52 -0800100 }
101
102 public Collection<Intent> getAllIntents() {
103 return intents.values();
104 }
105
Toshio Koideb609b3b2014-02-14 18:25:52 -0800106 public void addChangeListener(ChangedListener listener) {
107 listeners.add(listener);
108 }
109
110 public void removeChangedListener(ChangedListener listener) {
111 listeners.remove(listener);
112 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800113
114 //================================================================================
115 // methods that affect intents map (protected)
116 //================================================================================
117
118 protected void putIntent(Intent intent) {
119 if (intents.containsKey(intent.getId()))
120 removeIntent(intent.getId());
121 intents.put(intent.getId(), intent);
122 events.add(new ChangedEvent(ChangedEventType.ADDED, intent));
123 }
124
125 protected void removeIntent(String intentId) {
126 Intent intent = intents.remove(intentId);
127 if (intent == null) return;
128 events.add(new ChangedEvent(ChangedEventType.REMOVED, intent));
129 }
130
131 protected void setState(String intentId, IntentState state) {
132 Intent intent = intents.get(intentId);
133 if (intent == null) return;
134 intent.setState(state);
135 events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED, intent));
136 }
137
138 //================================================================================
139 // helper methods (protected)
140 //================================================================================
141
142 protected void handleAddOperation(IntentOperation operation) {
143 putIntent(operation.intent);
144 }
145
146 protected void handleRemoveOperation(IntentOperation operation) {
147 Intent intent = getIntent(operation.intent.getId());
148 if (intent == null) {
149 // TODO error handling
150 }
151 else {
152 setState(intent.getId(), IntentState.DEL_REQ);
153 }
154 }
155
156 protected void handleErrorOperation(IntentOperation operation) {
157 //TODO put error message into the intent
158
159 ErrorIntent errorIntent = (ErrorIntent) operation.intent;
160 Intent targetIntent = intents.get(errorIntent.getId());
161 if (targetIntent == null) {
162 // TODO error handling
163 return;
164 }
165
166 switch (targetIntent.getState()) {
167 case CREATED:
168 case INST_REQ:
169 case INST_ACK:
Toshio Koide066506e2014-02-20 19:52:09 -0800170 case REROUTE_REQ:
Toshio Koidedf2eab92014-02-20 11:24:59 -0800171 setState(targetIntent.getId(), IntentState.INST_NACK);
172 break;
173 case DEL_REQ:
174 setState(targetIntent.getId(), IntentState.DEL_PENDING);
175 break;
176 case INST_NACK:
177 case DEL_PENDING:
178 case DEL_ACK:
179 // do nothing
180 break;
181 }
182 }
183
184 protected void notifyEvents() {
185 for (ChangedListener listener: listeners) {
186 listener.intentsChange(events);
187 }
188 events.clear();
189 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800190}