2 Commits

Author SHA1 Message Date
Fabian Holzwarth
459bfcdd5f feat: added tests for client-server communication 2025-06-23 16:13:43 +02:00
Fabian Holzwarth
02886c38ea feat: fixed error in object serialization 2025-06-23 16:13:21 +02:00
30 changed files with 530 additions and 80 deletions

View File

@@ -13,6 +13,14 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketServer;
import de.dhbwstuttgart.server.packet.DebugPacket;
import de.dhbwstuttgart.server.packet.IPacket;
import de.dhbwstuttgart.server.packet.PacketContainer;
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;

View File

@@ -17,14 +17,17 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;
@@ -63,6 +66,7 @@ public class SocketClient extends WebSocketClient {
ConstraintSet<UnifyPair> unifyConstraintSet,
UnifyContext context
) throws JsonProcessingException {
try {
// wait for the connection to be set up
this.connectBlocking();
@@ -72,14 +76,12 @@ public class SocketClient extends WebSocketClient {
}
// send the unify task request
UnifyRequestPacket packet = new UnifyRequestPacket(finiteClosure, constraintSet, unifyConstraintSet);
UnifyRequestPacket packet = new UnifyRequestPacket(finiteClosure, constraintSet, unifyConstraintSet, context.placeholderRegistry());
String json = PacketContainer.serialize(packet);
try (FileWriter w = new FileWriter("./log.json")) {
w.write(json);
}
this.send(json);
// block the thread, until the connection is closed by the remote host (usually after sending the results)
this.waitUntilClosed();
// wait for the connection to fully close
@@ -146,6 +148,20 @@ public class SocketClient extends WebSocketClient {
e.printStackTrace();
}
@Override
public void onWebsocketPing(WebSocket conn, Framedata f) {
try {
// Send pong in response to ping
conn.sendFrame(new FramedataImpl1(f) {{
setOpcode(Opcode.PONG);
setPayload(f.getPayloadData());
}});
} catch (Exception e) {
System.err.println("Failed to send pong: " + e.getMessage());
}
super.onWebsocketPing(conn, f);
}
public void waitUntilClosed() throws InterruptedException {
closeLatch.await();
}

View File

@@ -18,13 +18,12 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledExecutorService;
@@ -37,10 +36,13 @@ import org.slf4j.LoggerFactory;
public class SocketServer extends WebSocketServer {
public static boolean active = false;
private static final Logger log = LoggerFactory.getLogger(SocketServer.class);
public SocketServer(int port) {
super(new InetSocketAddress(port));
SocketServer.active = true;
}
@Override
@@ -124,6 +126,8 @@ public class SocketServer extends WebSocketServer {
try {
var placeholderRegistry = new PlaceholderRegistry();
unifyRequestPacket.placeholders.forEach(placeholderRegistry::addPlaceholder);
var unifyContext = new UnifyContext(Writer.nullWriter(), false, true,
new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), null, placeholderRegistry)),
new UnifyTaskModel(), ForkJoinPool.commonPool(), placeholderRegistry
@@ -138,6 +142,12 @@ public class SocketServer extends WebSocketServer {
UnifyResultListenerImpl resultListener = new UnifyResultListenerImpl();
resultModel.addUnifyResultListener(resultListener);
try (FileWriter writer = new FileWriter("./parallel.log" + (SocketServer.active ? "s" : ""))) {
writer.write("placeholderRegistry: \n" + placeholderRegistry.toString());
}
catch (IOException exception) {}
TypeUnify.unifyParallel(
unifyConstraintSet.getUndConstraints(),
unifyConstraintSet.getOderConstraints(),
@@ -147,6 +157,7 @@ public class SocketServer extends WebSocketServer {
var resultSets = resultListener.getResults();
System.out.println("Finished unification for client " + webSocket.<SocketData>getAttachment().id);
sendMessage(webSocket, "Unification finished. Found " + resultSets.size() + " result sets");

View File

@@ -0,0 +1,21 @@
package de.dhbwstuttgart.server.packet;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
public class DebugPacket implements IPacket {
public SerialUUID a1;
public SerialUUID a2;
public SerialMap b1;
public SerialMap b2;
public SerialList<? extends ISerialNode> c1;
public SerialList<? extends ISerialNode> c2;
public SerialValue<?> d1;
public SerialValue<?> d2;
}

View File

@@ -23,6 +23,7 @@ public class PacketContainer {
public InvalidPacket invalidPacket = null;
public UnifyRequestPacket unifyRequestPacket = null;
public UnifyResultPacket unifyResultPacket = null;
public DebugPacket debugPacket = null;
/**
@@ -43,6 +44,8 @@ public class PacketContainer {
container.unifyRequestPacket = (UnifyRequestPacket) packet;
else if (packet instanceof UnifyResultPacket)
container.unifyResultPacket = (UnifyResultPacket) packet;
else if (packet instanceof DebugPacket)
container.debugPacket = (DebugPacket) packet;
// Add new packets here and in the deserialize method
return objectMapper.writeValueAsString(container);
@@ -70,10 +73,13 @@ public class PacketContainer {
return container.unifyRequestPacket;
if (container.unifyResultPacket != null)
return container.unifyResultPacket;
if (container.debugPacket != null)
return container.debugPacket;
// Add new packets here and in the serialize method
throw new RuntimeException("Cannot map received json to any known packet class");
} catch (Exception e) {
System.out.println(e);
InvalidPacket packet = new InvalidPacket();
packet.error = e.getMessage();
return packet;

View File

@@ -5,10 +5,12 @@ import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.ArrayList;
/**
* A packet to send all required data for the unification algorithm to the server and request the unification
@@ -19,6 +21,7 @@ public class UnifyRequestPacket implements IPacket {
public SerialMap constraintSet;
public SerialMap unifyConstraintSet;
public SerialMap serialKeyStorage;
public ArrayList<String> placeholders;
@JsonIgnore
private KeyStorage keyStorage = new KeyStorage();
@@ -30,12 +33,14 @@ public class UnifyRequestPacket implements IPacket {
public UnifyRequestPacket(
FiniteClosure finiteClosure,
ConstraintSet<Pair> constraintSet,
ConstraintSet<UnifyPair> unifyConstraintSet
ConstraintSet<UnifyPair> unifyConstraintSet,
PlaceholderRegistry placeholderRegistry
) {
this.finiteClosure = finiteClosure.toSerial(keyStorage);
this.constraintSet = constraintSet.toSerial(keyStorage);
this.unifyConstraintSet = unifyConstraintSet.toSerial(keyStorage);
this.serialKeyStorage = keyStorage.toSerial(keyStorage);
this.placeholders = placeholderRegistry.getPlaceholders();
}

View File

@@ -4,13 +4,14 @@ import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public class KeyStorage implements ISerializableData {
/**
* Store a unique identifier for every element, so it can be referenced in the json
*/
protected Map<ISerializableData, String> identifiers = new HashMap<>();
protected AtomicInteger identifierCount = new AtomicInteger();
/**
* Store the serialized element per identifier when serializing
*/
@@ -24,10 +25,8 @@ public class KeyStorage implements ISerializableData {
/**
* Retrieve or generate a new identifier for a constraint
*/
public String getIdentifier(ISerializableData element) {
final String identifier = this.identifiers.getOrDefault(element, "_" + identifiers.size());
this.identifiers.putIfAbsent(element, identifier);
return identifier;
public String getIdentifier() {
return this.identifierCount.incrementAndGet() + "_";
}
/**

View File

@@ -10,7 +10,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
property = "_t"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SerialMap.class, name = "m"),

View File

@@ -1,7 +1,25 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import java.io.IOException;
//@JsonSerialize(using = SerialValue.SerialValueSerializer.class)
//@JsonDeserialize(using = SerialValue.SerialValueDeserializer.class)
public class SerialValue<T> implements ISerialNode {
public T value;
public static final SerialValue<Object> NULL = new SerialValue<>(null);
@@ -25,4 +43,83 @@ public class SerialValue<T> implements ISerialNode {
public <A> A getOf(Class<A> targetClass) {
return this.assertValueOf(targetClass).value;
}
/*
public static class SerialValueSerializer extends JsonSerializer<SerialValue<?>> {
@Override
public void serialize(SerialValue<?> value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
writeValue(value, gen);
}
@Override
public void serializeWithType(SerialValue<?> value, JsonGenerator gen,
SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
// Properly delegate to Jackson to write type id
WritableTypeId typeId = typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.START_ARRAY));
// Jackson will manage writing the correct type ("v") as part of the type info
gen.writeString(typeId.id.toString()); // first element: the type ID, like "v"
writeValue(value, gen); // second element: the actual value
typeSer.writeTypeSuffix(gen, typeId);
}
private void writeValue(SerialValue<?> value, JsonGenerator gen) throws IOException {
if (value.value == null) gen.writeNull();
else if (value.value instanceof String sValue) gen.writeString(sValue);
else if (value.value instanceof Integer iValue) gen.writeNumber(iValue);
else if (value.value instanceof Byte bValue) gen.writeNumber(bValue);
else if (value.value instanceof Float fValue) gen.writeNumber(fValue);
else if (value.value instanceof Double dValue) gen.writeNumber(dValue);
else if (value.value instanceof Boolean bValue) gen.writeBoolean(bValue);
else throw new RuntimeException("Cannot serialize SerialValue with value of type " + value.value.getClass().getName());
}
}
public static class SerialValueDeserializer extends JsonDeserializer<SerialValue<?>> {
@Override
public SerialValue<?> deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
JsonNode field = p.getCodec().readTree(p);
if (field.isNull() || field.isEmpty()) return new SerialValue<>(null);
if (field.isBoolean()) return new SerialValue<>(field.asBoolean());
if (field.isTextual()) return new SerialValue<>(field.asText());
if (field.isInt()) return new SerialValue<>(field.asInt());
if (field.isLong()) return new SerialValue<>(field.asLong());
if (field.isFloat()) return new SerialValue<>(field.floatValue());
if (field.isDouble()) return new SerialValue<>(field.asDouble());
if (field.isNumber()) return new SerialValue<>(field.numberValue());
throw new RuntimeException("Cannot deserialize unknown type of value " + field.textValue() + "|" + field.isNull() + "|" + field.getNodeType() + " as SerialValue");
}
@Override
public SerialValue<?> deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
if (p.getCurrentToken() != JsonToken.START_ARRAY) {
throw JsonMappingException.from(p, "Expected START_ARRAY for deserialization of typed SerialValue");
}
p.nextToken(); // consume JsonToken.START_ARRAY
p.nextToken(); // consume type name ("v")
p.nextToken(); // move to value
// Extract value from node
Object value;
JsonToken token = p.currentToken();
switch (token) {
case VALUE_STRING -> value = p.getText();
case VALUE_NUMBER_INT -> value = p.getIntValue();
case VALUE_NUMBER_FLOAT -> value = p.getDoubleValue();
case VALUE_TRUE, VALUE_FALSE -> value = p.getBooleanValue();
case VALUE_NULL -> value = null;
default -> throw JsonMappingException.from(p, "Unsupported JSON token for SerialValue: " + token);
}
// consume and validate JsonToken.END_ARRAY
if (p.nextToken() != JsonToken.END_ARRAY) {
throw JsonMappingException.from(p, "Expected END_ARRAY after SerialValue value");
}
return new SerialValue<>(value);
}
}
*/
}

View File

@@ -18,6 +18,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class Constraint<A extends IConstraintElement> extends HashSet<A> implements ISerializableData {
private static final long serialVersionUID = 1L;
@@ -77,8 +78,9 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
}
public String toString() {
return super.toString() + "\nisInherited = " + isInherited + " isOveridden = " + isImplemented
+ methodSignatureConstraint
return super.toString() + "\nisInherited = " + isInherited
+ " isOveridden = " + isImplemented
+ " msc[" + methodSignatureConstraint.size() + "] = " + methodSignatureConstraint
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
+ "\n";
}
@@ -87,14 +89,18 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
return super.toString();
}
private String serialUUID = null;
@Override
public SerialUUID toSerial(KeyStorage keyStorage) {
final String uuid = keyStorage.getIdentifier(this);
final String uuid = serialUUID == null ? keyStorage.getIdentifier() : serialUUID;
if (serialUUID == null) serialUUID = uuid;
if (!keyStorage.isAlreadySerialized(uuid)) {
SerialMap serialized = new SerialMap();
keyStorage.putSerialized(uuid, serialized);
serialized.put("isInherited", isInherited);
serialized.put("isImplemented", isImplemented);
serialized.put("extendedConstraint", extendConstraint == null ? null : extendConstraint.toSerial(keyStorage));
Function<A, ISerialNode> pairMapper = pair -> {
if (pair instanceof Pair simplePair) return simplePair.toSerial(keyStorage);
@@ -120,6 +126,7 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
// retrieve the serialized data und start unserializing it
SerialMap data = keyStorage.getSerialized(uuid);
constraint.isInherited = data.getValue("isInherited").getOf(Boolean.class);
constraint.isImplemented = data.getValue("isImplemented").getOf(Boolean.class);
constraint.extendConstraint = Optional.ofNullable(data.getUUIDOrNull("extendedConstraint"))
.map(v -> Constraint.fromSerial(v, context, target, keyStorage))
.orElse(null);
@@ -135,11 +142,12 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
throw new RuntimeException("No serialization is supported for target type " + target.getName());
};
// TODO: löse das Rätsel der verschwindenden methodSignatureConstraint
constraint.methodSignatureConstraint = data.getList("methodSignatureConstraint")
.stream().map(pairUnmapper).collect(Collectors.toSet());
constraint.addAll(
data.getList("setElements")
.stream().map(pairUnmapper).collect(Collectors.toSet()));
.stream().map(pairUnmapper).toList());
}
return keyStorage.getUnserialized(uuid, Constraint.class);

View File

@@ -43,11 +43,25 @@ public class ConstraintSet<A extends IConstraintElement> implements ISerializabl
@Override
public String toString() {
BinaryOperator<String> b = (x, y) -> x + y;
return "\nUND:" + this.undConstraints.toString() + "\n" +
"ODER:" + this.oderConstraints.stream().reduce("", (x, y) -> x.toString() + "\n" + y, b);
return "\n" +
"UND:\n" + this.undConstraints.toString() +
"ODER:" + this.oderConstraints.stream().reduce("", (x, y) -> x + "\n\t" + y, b) +
"\n";
//cartesianProduct().toString();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ConstraintSet<?> other)) return false;
return Objects.equals(undConstraints, other.undConstraints)
&& Objects.equals(oderConstraints, other.oderConstraints);
}
@Override
public int hashCode() {
return Objects.hash(undConstraints, oderConstraints);
}
public Set<List<Constraint<A>>> cartesianProduct() {
Set<Constraint<A>> toAdd = new HashSet<>();
toAdd.add(undConstraints);

View File

@@ -75,7 +75,7 @@ public class Pair implements Serializable, IConstraintElement, ISerializableData
Operator = "<?";
*/
return "\n(" + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
return "\n(P: " + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
/*- Equals: " + bEqual*/
}

View File

@@ -28,12 +28,12 @@ public class PairTPHEqualTPH extends ResultPair<TypePlaceholder, TypePlaceholder
return serializedWrapper;
}
public static PairNoResult fromSerial2(SerialMap data, UnifyContext context) {
public static PairTPHEqualTPH fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairNoResult(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
return new PairTPHEqualTPH(
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
}

View File

@@ -6,6 +6,7 @@ import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.lang.reflect.Type;
/**
* Steht für A =. RefType
@@ -33,20 +34,20 @@ implements ISerializableData {
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();;
SerialMap serialized = new SerialMap();
serialized.put("left", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getRight().toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static PairNoResult fromSerial2(SerialMap data, UnifyContext context) {
public static PairTPHequalRefTypeOrWildcardType fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairNoResult(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
return new PairTPHequalRefTypeOrWildcardType(
(TypePlaceholder)RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}

View File

@@ -53,12 +53,12 @@ public class PairTPHsmallerTPH extends ResultPair<TypePlaceholder,TypePlaceholde
return serializedWrapper;
}
public static PairNoResult fromSerial2(SerialMap data, UnifyContext context) {
public static PairTPHsmallerTPH fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairNoResult(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
return new PairTPHsmallerTPH(
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
}

View File

@@ -69,7 +69,14 @@ implements ISerializableData {
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("type", this.getClass().getSimpleName());
String type = switch (this) {
case PairNoResult _ -> "pnr";
case PairTPHEqualTPH _ -> "ptet";
case PairTPHsmallerTPH _ -> "ptst";
case PairTPHequalRefTypeOrWildcardType _ -> "ptertwt";
default -> throw new RuntimeException("No type defined for ResultPair of class " + this.getClass().getName());
};
serialized.put("type", type);
// we only insert null for the object and expect the child classes to call this and override the value with themselves
serialized.put("object", SerialValue.NULL);
return serialized;
@@ -80,10 +87,12 @@ implements ISerializableData {
String type = data.getValue("type").getOf(String.class);
SerialMap object = data.getMap("object");
if (type.equals(PairNoResult.class.getSimpleName())) return (ResultPair)PairNoResult.fromSerial2(object, context);
else if (type.equals(PairTPHEqualTPH.class.getSimpleName())) return (ResultPair)PairTPHEqualTPH.fromSerial2(object, context);
else if (type.equals(PairTPHsmallerTPH.class.getSimpleName())) return (ResultPair)PairTPHsmallerTPH.fromSerial2(object, context);
else if (type.equals(PairTPHequalRefTypeOrWildcardType.class.getSimpleName())) return (ResultPair)PairTPHequalRefTypeOrWildcardType.fromSerial2(object, context);
else throw new RuntimeException("Could not unserialize class of unhandled type " + type);
return switch (type) {
case "pnr" -> (ResultPair) PairNoResult.fromSerial2(object, context);
case "ptet" -> (ResultPair) PairTPHEqualTPH.fromSerial2(object, context);
case "ptst" -> (ResultPair) PairTPHsmallerTPH.fromSerial2(object, context);
case "ptertwt" -> (ResultPair) PairTPHequalRefTypeOrWildcardType.fromSerial2(object, context);
default -> throw new RuntimeException("Could not unserialize class of unhandled type " + type);
};
}
}

View File

@@ -48,14 +48,19 @@ public class PlaceholderRegistry {
*/
private String getUppercaseTokenFromInt(int i) {
StringBuilder sb = new StringBuilder();
// sb.append("X");
while (i >= 0) {
sb.append((char)(i % 26 + 97));
sb.append((char)(i % 26 + 65));
i = i / 26 - 1;
}
//sb.append(suffix);
return sb.toString();
}
public ArrayList<String> getPlaceholders() {
return new ArrayList<>(this.existingPlaceholders);
}
@Override
public String toString() {
return this.existingPlaceholders.toString();

View File

@@ -2,6 +2,7 @@ package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.util.Logger;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Type;
@@ -56,7 +57,7 @@ public class TypeUnify {
unifyTask.compute();
return unifyContext.resultModel();
}
/**
* unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind
*/
@@ -65,6 +66,7 @@ public class TypeUnify {
UnifyContext context = unifyContext.newWithParallel(true).newWithExecutor(pool);
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, context, 0);
var result = joinFuture(unifyTask.compute());
try {
unifyContext.logFile().write("\nnoShortendElements: " + TypeUnifyTask.noShortendElements +"\n");
// logFile.flush();

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
@@ -12,7 +13,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* An extends wildcard type "? extends T".
*/
public final class ExtendsType extends WildcardType {
public final class ExtendsType extends WildcardType implements ISerializableData {
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);

View File

@@ -800,17 +800,6 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("pairs", SerialList.fromMapped(this.pairs, unifyPair -> unifyPair.toSerial(keyStorage)));
/*/
if (serialized != null) {
throw new RuntimeException(
"Check both: \n"
+ "-> " + this.pairs.toArray()[51] + "\n"
+ "-> " + this.pairs.toArray()[65] + "\n"
);
}
//*/
return serialized;
}

View File

@@ -1,14 +1,20 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FunInterfaceType extends ReferenceType {
public class FunInterfaceType extends ReferenceType implements ISerializableData {
final List<UnifyType> intfArgTypes;
final UnifyType intfReturnType;
final List<String> generics;
@@ -46,4 +52,29 @@ public class FunInterfaceType extends ReferenceType {
return args;
}
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
var serializedWrapper = super.toSerial(keyStorage);
SerialMap serialized = serializedWrapper.getMap("object");
serialized.put("intfArgTypes", SerialList.fromMapped(intfArgTypes, u -> u.toSerial(keyStorage)));
serialized.put("intfReturnType", intfReturnType.toSerial(keyStorage));
serialized.put("generics", SerialList.fromMapped(generics, SerialValue::new));
return serializedWrapper;
}
public static FunInterfaceType fromSerial(SerialMap data, UnifyContext context) {
var name = data.getValue("name").getOf(String.class);
var params = data.getList("params").assertListOfMaps().stream().map(
paramData -> UnifyType.fromSerial(paramData, context)).toList();
var intfArgTypes = data.getList("intfArgTypes").assertListOfMaps().stream().map(
argTypeData -> UnifyType.fromSerial(argTypeData, context)).toList();
var intfReturnType = UnifyType.fromSerial(data.getMap("intfReturnType"), context);
var generics = data.getList("generics").assertListOfValues().stream().map(
generic -> generic.getOf(String.class)).toList();
return new FunInterfaceType(name, new TypeParams(params), intfArgTypes, intfReturnType, generics);
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
@@ -16,7 +17,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
* A real function type in java.
* @author Florian Steurer
*/
public class FunNType extends UnifyType {
public class FunNType extends UnifyType implements ISerializableData {
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);

View File

@@ -201,6 +201,7 @@ public final class PlaceholderType extends UnifyType{
serialized.put("name", this.typeName);
// Placeholders never make use of the typeParams
serialized.put("isGenerated", IsGenerated);
serialized.put("wildcardable", wildcardable);
serialized.put("isInnerType", innerType);
serialized.put("variance", variance);
serialized.put("orCons", orCons);
@@ -214,11 +215,13 @@ public final class PlaceholderType extends UnifyType{
public static PlaceholderType fromSerial(SerialMap data, UnifyContext context) {
var name = data.getValue("name").getOf(String.class);
var isGenerated = data.getValue("isGenerated").getOf(Boolean.class);
var wildcardable = data.getValue("wildcardable").getOf(Boolean.class);
var isInnerType = data.getValue("isInnerType").getOf(Boolean.class);
var variance = data.getValue("variance").getOf(Integer.class);
var orCons = data.getValue("orCons").getOf(Number.class).byteValue();
var placeholderType = new PlaceholderType(name, isGenerated, context.placeholderRegistry());
placeholderType.setWildcardtable(wildcardable);
placeholderType.setInnerType(isInnerType);
placeholderType.setVariance(variance);
placeholderType.setOrCons(orCons);

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
@@ -14,7 +15,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
* @author Florian Steurer
*
*/
public class ReferenceType extends UnifyType {
public class ReferenceType extends UnifyType implements ISerializableData {
/**
* The buffered hashCode

View File

@@ -1,6 +1,7 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.util.Set;
@@ -92,6 +93,7 @@ public final class SuperType extends WildcardType {
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("wildcardedType", this.wildcardedType.toSerial(keyStorage));
serialized.put("params", SerialList.fromMapped(this.typeParams.get(), param -> param.toSerial(keyStorage)));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
@@ -100,8 +102,12 @@ public final class SuperType extends WildcardType {
}
public static SuperType fromSerial(SerialMap data, UnifyContext context) {
return new SuperType(
var params = data.getList("params").assertListOfMaps().stream().map(
paramData -> UnifyType.fromSerial(paramData, context)).toList();
var superType = new SuperType(
UnifyType.fromSerial(data.getMap("wildcardedType"), context)
);
superType.setTypeParams(new TypeParams(params));
return superType;
}
}

View File

@@ -255,7 +255,7 @@ public class UnifyPair implements IConstraintElement, ISerializableData {
+ "WC: " + ((PlaceholderType)rhs).isWildcardable()
+ ", IT: " + ((PlaceholderType)rhs).isInnerType();
}
var res = "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])";
var res = "(UP: " + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])";
var location = this.getLocation();
if (location != null) {
res += "@" + location.line() + " in " + location.file();
@@ -272,9 +272,12 @@ public class UnifyPair implements IConstraintElement, ISerializableData {
return ret;
}
*/
private String serialUUID = null;
public SerialUUID toSerial(KeyStorage keyStorage) {
String uuid = keyStorage.getIdentifier(this);
final String uuid = serialUUID == null ? keyStorage.getIdentifier() : serialUUID;
if (serialUUID == null) serialUUID = uuid;
if (!keyStorage.isAlreadySerialized(uuid)) {
SerialMap serialized = new SerialMap();
keyStorage.putSerialized(uuid, serialized);

View File

@@ -122,7 +122,17 @@ public abstract class UnifyType implements ISerializableData {
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("type", this.getClass().toString());
String type = switch (this) {
case FunInterfaceType _ -> "funi";
case ReferenceType _ -> "ref";
case ExtendsType _ -> "ext";
case SuperType _ -> "sup";
case FunNType _ -> "funn";
case PlaceholderType _ -> "tph";
default -> throw new RuntimeException("No type defined for UnifyType of class " + this.getClass().getName());
};
serialized.put("type", type);
// we only insert null for the object and expect the child classes to call this and override the value with themselves
serialized.put("object", SerialValue.NULL);
return serialized;
@@ -132,23 +142,14 @@ public abstract class UnifyType implements ISerializableData {
var type = data.getValue("type").getOf(String.class);
var object = data.getMap("object");
if (type.equals(ReferenceType.class.toString())) {
return ReferenceType.fromSerial(object, context);
}
else if (type.equals(ExtendsType.class.toString())) {
return ExtendsType.fromSerial(object, context);
}
else if (type.equals(SuperType.class.toString())) {
return SuperType.fromSerial(object, context);
}
else if (type.equals(FunNType.class.toString())) {
return FunNType.fromSerial(object, context);
}
else if (type.equals(PlaceholderType.class.toString())) {
return PlaceholderType.fromSerial(object, context);
}
else {
throw new RuntimeException("Could not unserialize class of unhandled type " + type);
}
return switch (type) {
case "funi" -> FunInterfaceType.fromSerial(object, context);
case "ref" -> ReferenceType.fromSerial(object, context);
case "ext" -> ExtendsType.fromSerial(object, context);
case "sup" -> SuperType.fromSerial(object, context);
case "funn" -> FunNType.fromSerial(object, context);
case "tph" -> PlaceholderType.fromSerial(object, context);
default -> throw new RuntimeException("Could not unserialize class of unhandled type " + type);
};
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.model;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import java.util.ArrayList;
import java.util.Collection;
@@ -7,7 +8,7 @@ import java.util.Collection;
* A wildcard type that is either a ExtendsType or a SuperType.
* @author Florian Steurer
*/
public abstract class WildcardType extends UnifyType {
public abstract class WildcardType extends UnifyType implements ISerializableData {
/**
* The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself.

View File

@@ -0,0 +1,101 @@
package server;
import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FunInterfaceType;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import java.io.Writer;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
class PacketExampleData {
static ConstraintSet<UnifyPair> getExampleUnifyPairConstraintSet(
UnifyContext unifyContext, String packagePath, int numUndCons, int numOderCons
) {
var constraintSet = new ConstraintSet<UnifyPair>();
for (int i = 0; i < numUndCons; i++) {
constraintSet.addUndConstraint(
getExampleUnifyPair(unifyContext, packagePath+"undCons.")
);
}
for (int i = 0; i < numOderCons; i++) {
var oderConstraint = new HashSet<Constraint<UnifyPair>>();
getExampleUnifyPairConstraint(unifyContext, packagePath+"oderCons.", i == 0);
constraintSet.addOderConstraint(oderConstraint);
}
return constraintSet;
}
static Constraint<UnifyPair> getExampleUnifyPairConstraint(UnifyContext unifyContext, String packagePath, boolean withExtends) {
return new Constraint<>(
!withExtends, true,
withExtends ? getExampleUnifyPairConstraint(unifyContext, packagePath+"extendConstraint.", false) : null,
withExtends ? new HashSet<>(List.of(
getExampleUnifyPair(unifyContext, packagePath+"methodSignatureConstraint.zero."),
getExampleUnifyPair(unifyContext, packagePath+"methodSignatureConstraint.one.")
)) : null
);
}
static UnifyPair getExampleUnifyPair(UnifyContext unifyContext, String packagePath) {
return new UnifyPair(
new ReferenceType(packagePath + "something", false),
new ExtendsType(
new SuperType(
new FunInterfaceType("lambda" + unifyContext.placeholderRegistry().generateFreshPlaceholderName(),
new TypeParams(),
List.of( // intfArgTypes
FunNType.getFunNType(new TypeParams(
List.of(
PlaceholderType.freshPlaceholder(unifyContext.placeholderRegistry()),
PlaceholderType.freshPlaceholder(unifyContext.placeholderRegistry())
)
))
),
PlaceholderType.freshPlaceholder(unifyContext.placeholderRegistry()), // intfReturnType
List.of( // generics
"ZA",
"ZB",
unifyContext.placeholderRegistry().generateFreshPlaceholderName()
)
)
)
),
PairOperator.SMALLERDOT,
new SourceLoc("test.jav", 10)
);
}
static UnifyContext createTestContext() {
var placeholderRegistry = new PlaceholderRegistry();
var nullWriter = Writer.nullWriter();
return new UnifyContext(nullWriter, false, true,
new UnifyResultModel(
new ConstraintSet<>(),
new FiniteClosure(
new HashSet<>(),
nullWriter,
placeholderRegistry)),
new UnifyTaskModel(),
ForkJoinPool.commonPool(),
placeholderRegistry
);
}
}

View File

@@ -0,0 +1,110 @@
package server;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.server.packet.DebugPacket;
import de.dhbwstuttgart.server.packet.IPacket;
import de.dhbwstuttgart.server.packet.InvalidPacket;
import de.dhbwstuttgart.server.packet.PacketContainer;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.io.Writer;
import java.util.HashSet;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BiFunction;
import org.junit.Test;
import static org.junit.Assert.*;
public class PacketTest {
@Test
public void serializeUnifyPair() throws JsonProcessingException {
UnifyContext unifyContext = PacketExampleData.createTestContext();
var original = PacketExampleData.getExampleUnifyPair(unifyContext, "de.test.");
var reconstruction = serializeAndDeserialize(original, unifyContext,
(o,k) -> UnifyPair.fromSerial((SerialUUID) o,unifyContext,k));
assertEquals(original.getClass(), reconstruction.getClass());
assertEquals(original.toString(), reconstruction.toString());
assertEquals(original, reconstruction);
}
@Test
public void serializeUnifyPairConstraint() throws JsonProcessingException {
UnifyContext unifyContext = PacketExampleData.createTestContext();
var original = PacketExampleData.getExampleUnifyPairConstraint(unifyContext, "de.", true);
var reconstruction = serializeAndDeserialize(original, unifyContext,
(o,k) -> Constraint.fromSerial((SerialUUID) o, unifyContext, UnifyPair.class, k));
assertEquals(original.getClass(), reconstruction.getClass());
assertEquals(original.toString(), reconstruction.toString());
assertEquals(original, reconstruction);
}
@Test
public void serializeUnifyPairConstraintSet() throws JsonProcessingException {
UnifyContext unifyContext = PacketExampleData.createTestContext();
var original = PacketExampleData.getExampleUnifyPairConstraintSet(unifyContext, "de.", 1, 2);
var reconstruction = serializeAndDeserialize(original, unifyContext,
(o,k) -> ConstraintSet.fromSerial((SerialMap) o, unifyContext, UnifyPair.class, k));
assertEquals(original.getClass(), reconstruction.getClass());
assertEquals(original.toString(), reconstruction.toString());
assertEquals(original, reconstruction);
}
/**
* Helper method for serializing an ISerialNode into JSON, then deserializing it
*/
private <T extends ISerialNode, R extends ISerializableData> R serializeAndDeserialize(
ISerializableData object, UnifyContext unifyContext, BiFunction<T, KeyStorage, R> fromSerial
) throws JsonProcessingException {
DebugPacket packet = new DebugPacket();
KeyStorage keyStorage = new KeyStorage();
var serializedObject = object.toSerial(keyStorage);
if (serializedObject instanceof SerialUUID sObject) packet.a1 = sObject;
if (serializedObject instanceof SerialMap sObject) packet.b1 = sObject;
if (serializedObject instanceof SerialList<?> sObject) packet.c1 = sObject;
if (serializedObject instanceof SerialValue<?> sObject) packet.d1 = sObject;
packet.b2 = keyStorage.toSerial(keyStorage);
DebugPacket reconstructedPacket = serializeAndDeserializePacket(packet);
KeyStorage reconstructedKeyStorage = KeyStorage.fromSerial(reconstructedPacket.b2, unifyContext);
ISerialNode reconstructedData = null;
if (serializedObject instanceof SerialUUID) reconstructedData = packet.a1;
if (serializedObject instanceof SerialMap) reconstructedData = packet.b1;
if (serializedObject instanceof SerialList<?>) reconstructedData = packet.c1;
if (serializedObject instanceof SerialValue<?>) reconstructedData = packet.d1;
assertNotNull(reconstructedData);
return fromSerial.apply( (T) reconstructedData, reconstructedKeyStorage);
}
private <T extends IPacket> T serializeAndDeserializePacket(T packet) throws JsonProcessingException {
String json = PacketContainer.serialize(packet);
IPacket reconstructedPacket = PacketContainer.deserialize(json);
assertNotNull(reconstructedPacket);
assertSame(packet.getClass(), reconstructedPacket.getClass());
return (T) reconstructedPacket;
}
}