blob: 9bdb21f9e94067510eea0c07fe03021ff81762c8 [file] [log] [blame]
package net.onrc.onos.core.intent;
import java.util.Collection;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import net.onrc.onos.core.intent.Intent.IntentState;
import net.onrc.onos.core.intent.runtime.IntentStateList;
/**
* @author Toshio Koide (t-koide@onlab.us)
*/
public class IntentMap {
private HashSet<ChangedListener> listeners = new HashSet<>();
private HashMap<String, Intent> intents = new HashMap<>();
private LinkedList<ChangedEvent> events = new LinkedList<>();
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 static 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);
}
//================================================================================
// public methods
//================================================================================
public void executeOperations(IntentOperationList operations) {
for (IntentOperation operation : operations) {
switch (operation.operator) {
case ADD:
handleAddOperation(operation);
break;
case REMOVE:
handleRemoveOperation(operation);
break;
case ERROR:
handleErrorOperation(operation);
break;
}
}
notifyEvents();
}
public void purge() {
LinkedList<String> removeIds = new LinkedList<>();
for (Entry<String, Intent> entry : intents.entrySet()) {
Intent intent = entry.getValue();
if (intent.getState() == IntentState.DEL_ACK
|| intent.getState() == IntentState.INST_NACK) {
removeIds.add(intent.getId());
}
}
for (String intentId : removeIds) {
removeIntent(intentId);
}
notifyEvents();
}
public void changeStates(IntentStateList states) {
for (Entry<String, IntentState> state : states.entrySet()) {
setState(state.getKey(), state.getValue());
}
notifyEvents();
}
public Intent getIntent(String intentId) {
return intents.get(intentId);
}
public Collection<Intent> getAllIntents() {
return intents.values();
}
public void addChangeListener(ChangedListener listener) {
listeners.add(listener);
}
public void removeChangedListener(ChangedListener listener) {
listeners.remove(listener);
}
//================================================================================
// methods that affect intents map (protected)
//================================================================================
protected void putIntent(Intent intent) {
if (intents.containsKey(intent.getId())) {
removeIntent(intent.getId());
}
intents.put(intent.getId(), intent);
events.add(new ChangedEvent(ChangedEventType.ADDED, intent));
}
protected void removeIntent(String intentId) {
Intent intent = intents.remove(intentId);
if (intent == null) {
return;
}
events.add(new ChangedEvent(ChangedEventType.REMOVED, intent));
}
protected void setState(String intentId, IntentState state) {
Intent intent = intents.get(intentId);
if (intent == null) {
return;
}
intent.setState(state);
events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED, intent));
}
//================================================================================
// helper methods (protected)
//================================================================================
protected void handleAddOperation(IntentOperation operation) {
putIntent(operation.intent);
}
protected void handleRemoveOperation(IntentOperation operation) {
Intent intent = getIntent(operation.intent.getId());
if (intent == null) {
// TODO error handling
return;
} else {
setState(intent.getId(), IntentState.DEL_REQ);
}
}
protected void handleErrorOperation(IntentOperation operation) {
//TODO put error message into the intent
ErrorIntent errorIntent = (ErrorIntent) operation.intent;
Intent targetIntent = intents.get(errorIntent.getId());
if (targetIntent == null) {
// TODO error handling
return;
}
switch (targetIntent.getState()) {
case CREATED:
case INST_REQ:
case INST_ACK:
case REROUTE_REQ:
setState(targetIntent.getId(), IntentState.INST_NACK);
break;
case DEL_REQ:
setState(targetIntent.getId(), IntentState.DEL_PENDING);
break;
case INST_NACK:
case DEL_PENDING:
case DEL_ACK:
// do nothing
break;
}
}
protected void notifyEvents() {
for (ChangedListener listener : listeners) {
listener.intentsChange(events);
}
events.clear();
}
}