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
Branches
No related tags found
No related merge requests found
...@@ -19,6 +19,40 @@ import java.util.Map; ...@@ -19,6 +19,40 @@ import java.util.Map;
*/ */
public class ASTNodeDeserializer extends StdDeserializer<ASTNode> { 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() { public ASTNodeDeserializer() {
this(null); this(null);
} }
...@@ -27,197 +61,301 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> { ...@@ -27,197 +61,301 @@ public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
super(vc); 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 @Override
public ASTNode deserialize(JsonParser jp, DeserializationContext ctxt) public RailwayContainer deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException { throws IOException {
JsonNode node = jp.getCodec().readTree(jp); 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; return result;
} }
private Object deserializeObject(JsonNode node) { private RailwayContainer deserializeRailwayContainer(JsonNode node) {
if (node.isObject()) { RailwayContainer instance = new RailwayContainer();
String kind = node.get("k").asText();
switch (kind) { // Route*
case "NT": for (JsonNode child : node.get("c").get("Route").get("c")) {
return deserializeNonterminal(node); instance.addRoute(deserializeRoute(child));
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);
} }
} 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) { private Region deserializeRegion(JsonNode node) {
final String packageName = "de.tudresden.inf.st.train.jastadd.ast"; 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 private Semaphore deserializeSemaphore(JsonNode node) {
String type = node.get("t").asText(); Semaphore instance = new Semaphore();
Class typeClass; // Id
try { Integer id = node.get("c").get("Id").get("v").asInt();
typeClass = Class.forName(packageName + "." + type); instance.setId(id);
} catch (ClassNotFoundException e) { idMap.put(id, instance);
throw new DeserializationException("Unable to find class of type " + type + " in package" + packageName, e);
} // Signal
switch (node.get("c").get("Signal").get("v").asText()) {
// create the instance case "GO":
ASTNode instance; instance.setSignal(Signal.GO);
try { break;
instance = (ASTNode) (typeClass.getConstructor().newInstance()); case "STOP":
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { instance.setSignal(Signal.STOP);
throw new DeserializationException("Unable to construct a nonterminal of type " + typeClass.getCanonicalName(), e); break;
} case "FAILURE":
instance.setSignal(Signal.FAILURE);
// call every setter we have a field for break;
Iterator<String> f = node.get("c").fieldNames(); default:
while (f.hasNext()) { throw new DeserializationException();
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();
} }
// get the method return instance;
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);
} }
} 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) { // ManagedEntry
throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName); 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 /// ManagedExit
try { if (!node.get("c").get("ManagedExit").get("v").isNull()) {
method.invoke(instance, parameter); this.listRouteManagedExit.add(new IM<Route>(instance, node.get("c").get("ManagedExit").get("v").asInt()));
} catch (IllegalAccessException | InvocationTargetException e) { }
throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName, e); 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; return instance;
} }
private ASTNode deserializeOpt(JsonNode node) { private Sensor deserializeSensor(JsonNode node) {
if (node.has("c")) { Sensor instance = new Sensor();
// opts can only contain Nonterminals
ASTNode value = deserializeNonterminal(node.get("c"));
return new Opt(value);
} else { // Id
return new Opt(); 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) { private TrackElement deserializeTrackElement(JsonNode node) {
// get the type name
String typeName = node.get("t").asText(); TrackElement instance;
// first try the builtin types if (node.get("t").asText().equals("Segment")) {
if (typeName.equals("int") || typeName.equals("Integer")) { instance = deserializeSegment(node);
return node.get("v").asInt(); } else if (node.get("t").asText().equals("Switch")) {
} else if (typeName.equals("boolean") || typeName.equals("Boolean")) { instance = deserializeSwitch(node);
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();
} else { } 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) { // ManagedConnectsTo
// get the type name for (JsonNode child : node.get("c").get("ManagedConnectsTo").get("c")) {
String typeName = node.get("t").asText(); int ref = child.get("v").asInt();
this.listTrackElementManagedConnectsTo.add(new IM<TrackElement>(instance, ref));
}
Class type; return instance;
try {
type = Class.forName(typeName);
} catch (ClassNotFoundException e) {
throw new DeserializationException("cannot create enum of type " + typeName, e);
} }
Method valueOf; private Segment deserializeSegment(JsonNode node) {
try { Segment instance = new Segment();
valueOf = type.getMethod("valueOf", String.class);
} catch (NoSuchMethodException e) { // Length
throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e); 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()); return instance;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e);
} }
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) { // ManagedPositions
List list = new List(); for (JsonNode child : node.get("c").get("ManagedPositions").get("c")) {
Iterator<JsonNode> it = node.get("c").elements(); int ref = child.get("v").asInt();
while (it.hasNext()) { this.listSwitchManagedPositions.add(new IM<Switch>(instance, ref));
JsonNode child = it.next();
// lists can only contain Nonterminals
list.add(deserializeNonterminal(child));
} }
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