package org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.client.serializers.json;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.opennaas.extensions.openflowswitch.driver.floodlight.protocol.client.wrappers.FloodlightOFFlowsWrapper;
import org.opennaas.extensions.openflowswitch.model.FloodlightOFAction;
import org.opennaas.extensions.openflowswitch.model.FloodlightOFFlow;
import org.opennaas.extensions.openflowswitch.model.FloodlightOFMatch;
public class FloodlightOFFlowsWrapperJSONDeserializer extends JsonDeserializer<FloodlightOFFlowsWrapper> {
private Log log = LogFactory.getLog(FloodlightOFFlowsWrapperJSONDeserializer.class);
@Override
public FloodlightOFFlowsWrapper deserialize(JsonParser jp, DeserializationContext ctx) throws IOException, JsonProcessingException {
// initialize object wrapper
FloodlightOFFlowsWrapper wrapper = new FloodlightOFFlowsWrapper();
// switch IDs loop
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
if ((jp.getCurrentToken()) != JsonToken.FIELD_NAME) {
throw new IOException("Expected FIELD_NAME and it was " + jp.getCurrentToken());
}
// get switch ID
String switchId = jp.getCurrentName();
// expect switch start object
JsonToken token = jp.nextToken();
if (token == JsonToken.VALUE_NULL) {
// no object inside, stop deserializing
break;
}
else if (token != JsonToken.START_OBJECT) {
throw new IOException("Expected START_OBJECT and it was " + jp.getCurrentToken());
}
// flow IDs loop
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
if ((jp.getCurrentToken()) != JsonToken.FIELD_NAME) {
throw new IOException("Expected FIELD_NAME and it was " + jp.getCurrentToken());
}
// get flow name and go to next token
String flowName = jp.getCurrentName();
jp.nextToken();
// initialize the new flow
FloodlightOFFlow flow = new FloodlightOFFlow();
flow.setName(flowName);
flow.setSwitchId(switchId);
FloodlightOFMatch match = new FloodlightOFMatch();
List<FloodlightOFAction> actions = new ArrayList<FloodlightOFAction>(0);
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Expected START_OBJECT and it was " + jp.getCurrentToken());
}
// flow fields loop
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
if ((jp.getCurrentToken()) != JsonToken.FIELD_NAME) {
throw new IOException("Expected FIELD_NAME and it was " + jp.getCurrentToken());
}
// get token name and go to the next token
String nodeName = jp.getCurrentName();
jp.nextToken();
if (jp.getText().equals(""))
continue;
if (nodeName == "actions") {
actions = parseActions(jp);
} else if (nodeName == "priority")
flow.setPriority(jp.getText());
else if (nodeName == "match") {
match = parseMatch(jp);
}
}
// set flows and match
flow.setMatch(match);
flow.setActions(actions);
// set active true, it is never sent by Floodlight, if the flow is returned it is active
flow.setActive(true);
// add flow
wrapper.add(flow);
}
}
return wrapper;
}
private List<FloodlightOFAction> parseActions(JsonParser jp) throws JsonParseException, IOException {
// initialize action list
List<FloodlightOFAction> actions = new ArrayList<FloodlightOFAction>();
// expect start array
if (jp.getCurrentToken() != JsonToken.START_ARRAY) {
throw new IOException("Expected START_ARRAY and it was " + jp.getCurrentToken());
}
// action array loop
while (jp.nextToken() != JsonToken.END_ARRAY) {
// expect action start object
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
throw new IOException("Expected START_OBJECT and it was " + jp.getCurrentToken());
}
Map<String, String> actionMap = new HashMap<String, String>();
// action fields loop
while (jp.nextToken() != JsonToken.END_OBJECT) {
if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
throw new IOException("Expected FIELD_NAME and it was " + jp.getCurrentToken());
}
// get field name and go to next token
String fieldName = jp.getCurrentName();
jp.nextToken();
actionMap.put(fieldName.toLowerCase(), jp.getText());
}
// fill action list following some rules, by now only OUTPUT actions are parsed
if (actionMap.get("type").equalsIgnoreCase(FloodlightOFAction.TYPE_OUTPUT.toLowerCase())) {
// fill action
FloodlightOFAction action = new FloodlightOFAction();
// set type and value
action.setType(FloodlightOFAction.TYPE_OUTPUT.toLowerCase());
action.setValue(actionMap.get("port"));
actions.add(action);
} else {
// no more types known
log.info("Property type unknown: " + actionMap.get("type"));
}
}
return actions;
}
private FloodlightOFMatch parseMatch(JsonParser jp) throws JsonParseException, IOException {
// initialize match
FloodlightOFMatch match = new FloodlightOFMatch();
// match fields loop
while ((jp.nextToken()) != JsonToken.END_OBJECT) {
if ((jp.getCurrentToken()) != JsonToken.FIELD_NAME) {
throw new IOException("Expected FIELD_NAME and it was " + jp.getCurrentToken());
}
// get field name and go to next token
String fieldName = jp.getCurrentName();
jp.nextToken();
if (fieldName == "wildcards")
match.setWildcards(jp.getText());
else if (fieldName == "inputPort")
match.setIngressPort(jp.getText());
else if (fieldName == "dataLayerSource")
match.setSrcMac(jp.getText());
else if (fieldName == "dataLayerDestination")
match.setDstMac(jp.getText());
else if (fieldName == "dataLayerVirtualLan")
match.setVlanId(jp.getText());
else if (fieldName == "dataLayerVirtualLanPriorityCodePoint")
match.setVlanPriority(jp.getText());
else if (fieldName == "dataLayerType")
match.setEtherType(jp.getText());
else if (fieldName == "networkTypeOfService")
match.setTosBits(jp.getText());
else if (fieldName == "networkProtocol")
match.setProtocol(jp.getText());
else if (fieldName == "networkSource")
match.setSrcIp(jp.getText());
else if (fieldName == "networkDestination")
match.setDstIp(jp.getText());
else if (fieldName == "transportSource")
match.setSrcPort(jp.getText());
else if (fieldName == "transportDestination")
match.setDstPort(jp.getText());
}
return match;
}
}