Skip to content
Snippets Groups Projects
Commit 88748df4 authored by Johannes Mey's avatar Johannes Mey
Browse files

completely rewrite deserializer. remove failing serializer fo now

parent cdfb8b1b
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,40 @@ import java.util.Map;
*/
public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
public static class IM<Node extends ASTNode> {
private final Node node;
private final int ref;
public IM(Node node, int ref) {
this.node = node;
this.ref = ref;
}
public Node getNode() {
return node;
}
public int getRef() {
return ref;
}
@Override
public int hashCode() {
return node.hashCode() ^ Integer.hashCode(ref);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof IM)) return false;
IM pairo = (IM) o;
return this.node.equals(pairo.getNode()) &&
this.ref == pairo.getRef();
}
}
final String packageName = "de.tudresden.inf.st.train.jastadd.ast";
public ASTNodeDeserializer() {
this(null);
}
......@@ -27,197 +61,301 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
super(vc);
}
private Map<Integer, RailwayElement> idMap = new HashMap<>();
private java.util.List<IM<Route>> listRouteManagedRequiredSensors = new ArrayList<>();
private java.util.List<IM<Route>> listRouteManagedEntry = new ArrayList<>();
private java.util.List<IM<Route>> listRouteManagedExit = new ArrayList<>();
private java.util.List<IM<SwitchPosition>> listSwitchPositionManagedTarget = new ArrayList<>();
private java.util.List<IM<Sensor>> listSensorManagedMonitors = new ArrayList<>();
private java.util.List<IM<Sensor>> listSensorManagedRequiringRoutes = new ArrayList<>();
private java.util.List<IM<TrackElement>> listTrackElementManagedMonitoredBy = new ArrayList<>();
private java.util.List<IM<TrackElement>> listTrackElementManagedConnectsTo = new ArrayList<>();
private java.util.List<IM<Switch>> listSwitchManagedPositions = new ArrayList<>();
private Map<Integer, ASTNode> idMap = new HashMap<>();
@Override
public ASTNode deserialize(JsonParser jp, DeserializationContext ctxt)
public RailwayContainer deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
RailwayContainer result = deserializeRailwayContainer(node);
ASTNode result = (ASTNode) deserializeObject(node);
for (IM<Route> e : listRouteManagedRequiredSensors) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedRequiredSensors().add((Sensor)idMap.get(e.getRef()));
}
for (IM<Route> e : listRouteManagedEntry) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().setManagedEntry((Semaphore)idMap.get(e.getRef()));
}
for (IM<Route> e : listRouteManagedExit) {
e.getNode().setManagedExit((Semaphore)idMap.get(e.getRef()));
}
for (IM<SwitchPosition> e : listSwitchPositionManagedTarget) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().setManagedTarget((Switch)idMap.get(e.getRef()));
}
for (IM<Sensor> e : listSensorManagedMonitors) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedMonitors().add((TrackElement)idMap.get(e.getRef()));
}
for (IM<Sensor> e : listSensorManagedRequiringRoutes) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedRequiringRoutes().add((Route)idMap.get(e.getRef()));
}
for (IM<TrackElement> e : listTrackElementManagedMonitoredBy) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedMonitoredBy().add((Sensor)idMap.get(e.getRef()));
}
for (IM<TrackElement> e : listTrackElementManagedConnectsTo) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedConnectsTo().add((TrackElement)idMap.get(e.getRef()));
}
for (IM<Switch> e : listSwitchManagedPositions) {
if (idMap.get(e.getRef()) == null) {
throw new DeserializationException();
}
e.getNode().getManagedPositions().add((SwitchPosition)idMap.get(e.getRef()));
}
return result;
}
private Object deserializeObject(JsonNode node) {
if (node.isObject()) {
String kind = node.get("k").asText();
switch (kind) {
case "NT":
return deserializeNonterminal(node);
case "List":
return deserializeList(node);
case "Opt":
return deserializeOpt(node);
case "i":
return deserializeIntrinsicRef(node);
case "t":
return deserializeTerminal(node);
case "enum":
return deserializeEnum(node);
default:
throw new DeserializationException("cannot deserialize node of unknown kind " + kind);
private RailwayContainer deserializeRailwayContainer(JsonNode node) {
RailwayContainer instance = new RailwayContainer();
// Route*
for (JsonNode child : node.get("c").get("Route").get("c")) {
instance.addRoute(deserializeRoute(child));
}
} else {
throw new DeserializationException("cannot deserialize non-object node as object node!");
// Region*
for (JsonNode child : node.get("c").get("Region").get("c")) {
instance.addRegion(deserializeRegion(child));
}
return instance;
}
private ASTNode deserializeIntrinsicRef(JsonNode node) {
final String packageName = "de.tudresden.inf.st.train.jastadd.ast";
private Region deserializeRegion(JsonNode node) {
Region instance = new Region();
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
return null;
// TrackElement*
for (JsonNode child : node.get("c").get("TrackElement").get("c")) {
instance.addTrackElement(deserializeTrackElement(child));
}
private ASTNode deserializeNonterminal(JsonNode node) {
// Sensor*
for (JsonNode child : node.get("c").get("Sensor").get("c")) {
instance.addSensor(deserializeSensor(child));
}
final String packageName = "de.tudresden.inf.st.train.jastadd.ast";
return instance;
}
// get the type we want to create
String type = node.get("t").asText();
Class typeClass;
try {
typeClass = Class.forName(packageName + "." + type);
} catch (ClassNotFoundException e) {
throw new DeserializationException("Unable to find class of type " + type + " in package" + packageName, e);
}
// create the instance
ASTNode instance;
try {
instance = (ASTNode) (typeClass.getConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new DeserializationException("Unable to construct a nonterminal of type " + typeClass.getCanonicalName(), e);
}
// call every setter we have a field for
Iterator<String> f = node.get("c").fieldNames();
while (f.hasNext()) {
String fieldName = f.next();
// serialize the parameter
Object parameter = deserializeObject(node.get("c").get(fieldName));
// find the setter to call
boolean isList = node.get("c").get(fieldName).get("k").asText().equals("List");
boolean isOpt = node.get("c").get(fieldName).get("k").asText().equals("Opt");
// ... by getting its name
String setterName = "set" + fieldName + (isList ? "List" : "") + (isOpt ? "Opt" : "");
// ... and its type
Class setterType;
if (isList) {
setterType = List.class;
} else if (isOpt) {
setterType = Opt.class;
} else {
setterType = parameter.getClass();
private Semaphore deserializeSemaphore(JsonNode node) {
Semaphore instance = new Semaphore();
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
// Signal
switch (node.get("c").get("Signal").get("v").asText()) {
case "GO":
instance.setSignal(Signal.GO);
break;
case "STOP":
instance.setSignal(Signal.STOP);
break;
case "FAILURE":
instance.setSignal(Signal.FAILURE);
break;
default:
throw new DeserializationException();
}
// get the method
Method method = null;
try {
method = typeClass.getMethod(setterName, setterType);
} catch (NoSuchMethodException e1) {
try {
if (setterType.equals(Integer.class)) {
method = typeClass.getMethod(setterName, int.class);
} else if (setterType.equals(Double.class)) {
method = typeClass.getMethod(setterName, double.class);
} else if (setterType.equals(Long.class)) {
method = typeClass.getMethod(setterName, long.class);
} else if (setterType.equals(Character.class)) {
method = typeClass.getMethod(setterName, char.class);
} else if (setterType.equals(Boolean.class)) {
method = typeClass.getMethod(setterName, boolean.class);
} else if (setterType.equals(Float.class)) {
method = typeClass.getMethod(setterName, float.class);
return instance;
}
} catch (NoSuchMethodException e2) {
throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName, e2);
private Route deserializeRoute(JsonNode node) {
Route instance = new Route();
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
// Active
instance.setActive(node.get("c").get("Active").get("v").asBoolean());
// SwitchPosition
for (JsonNode child : node.get("c").get("SwitchPosition").get("c")) {
instance.addSwitchPosition(deserializeSwitchPosition(child));
}
// ManagedRequiredSensors
for (JsonNode child : node.get("c").get("ManagedRequiredSensors").get("c")) {
int ref = child.get("v").asInt();
this.listRouteManagedRequiredSensors.add(new IM<Route>(instance, ref));
}
if (method == null) {
throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName);
// ManagedEntry
if (!node.get("c").get("ManagedEntry").get("v").isNull()) {
this.listRouteManagedEntry.add(new IM<Route>(instance, node.get("c").get("ManagedEntry").get("v").asInt()));
}
// invoke the method on the instance with the parameter
try {
method.invoke(instance, parameter);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName, e);
/// ManagedExit
if (!node.get("c").get("ManagedExit").get("v").isNull()) {
this.listRouteManagedExit.add(new IM<Route>(instance, node.get("c").get("ManagedExit").get("v").asInt()));
}
return instance;
}
private SwitchPosition deserializeSwitchPosition(JsonNode node) {
SwitchPosition instance = new SwitchPosition();
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
// Position
switch (node.get("c").get("Position").get("v").asText()) {
case "FAILURE":
instance.setPosition(Position.FAILURE);
break;
case "STRAIGHT":
instance.setPosition(Position.STRAIGHT);
break;
case "DIVERGING":
instance.setPosition(Position.DIVERGING);
break;
default:
throw new DeserializationException();
}
// finally, return the instance
// ManagedTarget
this.listSwitchPositionManagedTarget.add(new IM<SwitchPosition>(instance, node.get("c").get("ManagedTarget").get("v").asInt()));
return instance;
}
private ASTNode deserializeOpt(JsonNode node) {
if (node.has("c")) {
// opts can only contain Nonterminals
ASTNode value = deserializeNonterminal(node.get("c"));
return new Opt(value);
private Sensor deserializeSensor(JsonNode node) {
Sensor instance = new Sensor();
} else {
return new Opt();
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
// ManagedMonitors
for (JsonNode child : node.get("c").get("ManagedMonitors").get("c")) {
int ref = child.get("v").asInt();
this.listSensorManagedMonitors.add(new IM<Sensor>(instance, ref));
}
// ManagedRequiringRoutes
for (JsonNode child : node.get("c").get("ManagedRequiringRoutes").get("c")) {
int ref = child.get("v").asInt();
this.listSensorManagedRequiringRoutes.add(new IM<Sensor>(instance, ref));
}
return instance;
}
private Object deserializeTerminal(JsonNode node) {
// get the type name
String typeName = node.get("t").asText();
private TrackElement deserializeTrackElement(JsonNode node) {
TrackElement instance;
// first try the builtin types
if (typeName.equals("int") || typeName.equals("Integer")) {
return node.get("v").asInt();
} else if (typeName.equals("boolean") || typeName.equals("Boolean")) {
return node.get("v").asBoolean();
} else if (typeName.equals("double") || typeName.equals("Double")) {
return node.get("v").asDouble();
} else if (typeName.equals("String")) {
return node.get("v").asText();
} else if (typeName.equals("long") || typeName.equals("Long")) {
return node.get("v").asLong();
if (node.get("t").asText().equals("Segment")) {
instance = deserializeSegment(node);
} else if (node.get("t").asText().equals("Switch")) {
instance = deserializeSwitch(node);
} else {
throw new DeserializationException("cannot create object of type " + typeName);
throw new DeserializationException();
}
// Id
Integer id = node.get("c").get("Id").get("v").asInt();
instance.setId(id);
idMap.put(id, instance);
// ManagedMonitoredBy
for (JsonNode child : node.get("c").get("ManagedMonitoredBy").get("c")) {
int ref = child.get("v").asInt();
this.listTrackElementManagedMonitoredBy.add(new IM<TrackElement>(instance, ref));
}
private Enum deserializeEnum(JsonNode node) {
// get the type name
String typeName = node.get("t").asText();
// ManagedConnectsTo
for (JsonNode child : node.get("c").get("ManagedConnectsTo").get("c")) {
int ref = child.get("v").asInt();
this.listTrackElementManagedConnectsTo.add(new IM<TrackElement>(instance, ref));
}
Class type;
try {
type = Class.forName(typeName);
} catch (ClassNotFoundException e) {
throw new DeserializationException("cannot create enum of type " + typeName, e);
return instance;
}
Method valueOf;
try {
valueOf = type.getMethod("valueOf", String.class);
} catch (NoSuchMethodException e) {
throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e);
private Segment deserializeSegment(JsonNode node) {
Segment instance = new Segment();
// Length
instance.setLength(node.get("c").get("Length").get("v").asInt());
// Semaphore*
for (JsonNode child : node.get("c").get("Semaphore").get("c")) {
instance.addSemaphore(deserializeSemaphore(child));
}
try {
return (Enum) valueOf.invoke(null, node.get("v").asText());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e);
return instance;
}
private Switch deserializeSwitch(JsonNode node) {
Switch instance = new Switch();
// CurrentPosition
switch (node.get("c").get("CurrentPosition").get("v").asText()) {
case "FAILURE":
instance.setCurrentPosition(Position.FAILURE);
break;
case "STRAIGHT":
instance.setCurrentPosition(Position.STRAIGHT);
break;
case "DIVERGING":
instance.setCurrentPosition(Position.DIVERGING);
break;
default:
throw new DeserializationException();
}
private List deserializeList(JsonNode node) {
List list = new List();
Iterator<JsonNode> it = node.get("c").elements();
while (it.hasNext()) {
JsonNode child = it.next();
// lists can only contain Nonterminals
list.add(deserializeNonterminal(child));
// ManagedPositions
for (JsonNode child : node.get("c").get("ManagedPositions").get("c")) {
int ref = child.get("v").asInt();
this.listSwitchManagedPositions.add(new IM<Switch>(instance, ref));
}
return list;
return instance;
}
}
package de.tudresden.inf.st.train.jastadd.driver.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import de.tudresden.inf.st.train.jastadd.ast.ASTNode;
import de.tudresden.inf.st.train.jastadd.ast.ASTNodeAnnotation.Child;
import de.tudresden.inf.st.train.jastadd.ast.ASTNodeAnnotation.ListChild;
import de.tudresden.inf.st.train.jastadd.ast.ASTNodeAnnotation.OptChild;
import de.tudresden.inf.st.train.jastadd.ast.ASTNodeAnnotation.Token;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ASTNodeSerializer extends StdSerializer<ASTNode> {
public ASTNodeSerializer() {
this(null);
}
public ASTNodeSerializer(Class<ASTNode> t) {
super(t);
}
@Override
public void serialize(
ASTNode value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
jgen.writeStringField("k", "NT");
jgen.writeStringField("t", value.getClass().getSimpleName());
jgen.writeObjectFieldStart("c");
for (Method m : value.getClass().getMethods()) {
try {
if (m.getAnnotation(Child.class) != null) {
jgen.writeFieldName(m.getAnnotation(Child.class).name());
provider.defaultSerializeValue(m.invoke(value), jgen);
} else if (m.getAnnotation(Token.class) != null) {
jgen.writeFieldName(m.getAnnotation(Token.class).name());
jgen.writeStartObject();
if (m.getReturnType().isEnum()) {
jgen.writeStringField("k", "enum");
jgen.writeFieldName("v");
provider.defaultSerializeValue(m.invoke(value), jgen);
} else if (ASTNode.class.isAssignableFrom(m.getReturnType())) {
jgen.writeStringField("k", "i");
jgen.writeFieldName("v");
// TODO!!!
provider.defaultSerializeValue(m.invoke(value), jgen);
} else {
jgen.writeStringField("k", "t");
jgen.writeStringField("t", m.getReturnType().getName());
jgen.writeFieldName("v");
provider.defaultSerializeValue(m.invoke(value), jgen);
}
jgen.writeEndObject();
} else if (m.getAnnotation(ListChild.class) != null) {
jgen.writeFieldName(m.getAnnotation(ListChild.class).name());
provider.defaultSerializeValue(m.invoke(value), jgen);
} else if (m.getAnnotation(OptChild.class) != null) {
jgen.writeFieldName(m.getAnnotation(OptChild.class).name());
provider.defaultSerializeValue(m.invoke(value), jgen);
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
jgen.writeEndObject();
jgen.writeEndObject();
}
}
package de.tudresden.inf.st.train.jastadd.driver.serializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import de.tudresden.inf.st.train.jastadd.ast.ASTNode;
import de.tudresden.inf.st.train.jastadd.ast.List;
import de.tudresden.inf.st.train.jastadd.ast.Opt;
import de.tudresden.inf.st.train.jastadd.ast.RailwayContainer;
import java.io.File;
import java.io.IOException;
public class JsonSerializer {
public static void write(RailwayContainer r, String fileName) {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
SimpleModule module = new SimpleModule();
module.addSerializer(ASTNode.class, new ASTNodeSerializer());
module.addSerializer(List.class, new ListSerializer());
module.addSerializer(Opt.class, new OptSerializer());
mapper.registerModule(module);
try {
mapper.writeValue(new File(fileName), r);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package de.tudresden.inf.st.train.jastadd.driver.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import de.tudresden.inf.st.train.jastadd.ast.ASTNode;
import de.tudresden.inf.st.train.jastadd.ast.List;
import java.io.IOException;
public class ListSerializer extends StdSerializer<List> {
public ListSerializer() {
this(null);
}
public ListSerializer(Class<List> t) {
super(t);
}
@Override
public void serialize(
List value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
jgen.writeStringField("k", "List");
jgen.writeArrayFieldStart("c");
for (ASTNode child : (Iterable<ASTNode>) value.astChildren()) {
provider.defaultSerializeValue(child, jgen);
}
jgen.writeEndArray();
jgen.writeEndObject();
}
}
package de.tudresden.inf.st.train.jastadd.driver.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import de.tudresden.inf.st.train.jastadd.ast.ASTNode;
import de.tudresden.inf.st.train.jastadd.ast.Opt;
import java.io.IOException;
public class OptSerializer extends StdSerializer<Opt> {
public OptSerializer() {
this(null);
}
public OptSerializer(Class<Opt> t) {
super(t);
}
@Override
public void serialize(
Opt value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStartObject();
jgen.writeStringField("k", "Opt");
if (value.getNumChild() > 0) {
jgen.writeFieldName("c");
for (ASTNode child : (Iterable<ASTNode>) value.astChildren()) {
provider.defaultSerializeValue(child, jgen);
}
}
jgen.writeEndObject();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment