Commit 27b12f3f authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

add test for JoltTransformV4toV5

parent 421ec71b
Pipeline #66282 failed with stages
in 45 seconds
[
{
// Changes
// rename: scenario/attributesSimulation/useRandomSeed to useFixedSeed
// rename: scenario/attributesSimulation/randomSeed to fixedSeed
// add: scenario/attributesSimulation/randomSeed/simulationSeed
"operation": "shift",
"spec": {
"name": "&",
......
[
{
// Changes
// remove: scenario/attributesSimulation/needsBoundary
// remove attributes from processor PedestrianOverlapProcessor [removed via java]
"operation": "shift",
"spec": {
"name": "&",
......
......@@ -7,7 +7,9 @@ import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;
/** Versions in strict order from oldest to newest. */
/**
* Versions in strict order from oldest to newest.
*/
public enum Version {
UNDEFINED("undefined"),
......@@ -15,7 +17,8 @@ public enum Version {
V0_1("0.1"),
V0_2("0.2"),
V0_3("0.3"),
V0_4("0.4");
V0_4("0.4"),
V0_5("0.5");
private String label;
......@@ -40,45 +43,45 @@ public enum Version {
return null;
}
private static int versionId(Version curr){
private static int versionId(Version curr) {
Version[] versions = values();
for ( int i = 0 ; i < versions.length ; i++){
if (curr.equals(versions[i])){
return i;
for (int i = 0; i < versions.length; i++) {
if (curr.equals(versions[i])) {
return i;
}
}
throw new IllegalArgumentException("Value not in Version Enumeration " + curr.toString());
}
public static String[] stringValues(){
public static String[] stringValues() {
return Arrays.stream(values()).map(v -> v.label().replace(' ', '_')).toArray(String[]::new);
}
public static String[] stringValues(Version startFrom){
public static String[] stringValues(Version startFrom) {
int min = startFrom.ordinal();
return Arrays.stream(values()).filter(v -> v.ordinal() >= min).map(v -> v.label().replace(' ', '_')).toArray(String[]::new);
}
public Version nextVersion(){
int nextId = versionId(this) == (values().length -1) ? versionId(this) : versionId(this) + 1;
public Version nextVersion() {
int nextId = versionId(this) == (values().length - 1) ? versionId(this) : versionId(this) + 1;
return values()[nextId];
}
public Version previousVersion(){
public Version previousVersion() {
int nextId = versionId(this) == 0 ? versionId(this) : versionId(this) - 1;
return values()[nextId];
}
public static Version[] listToLatest (Version v){
int start = versionId(v) == (values().length -1) ? versionId(v) : versionId(v) + 1;
public static Version[] listToLatest(Version v) {
int start = versionId(v) == (values().length - 1) ? versionId(v) : versionId(v) + 1;
int end = values().length;
Version[] ret = new Version[end-start];
System.arraycopy(values(), start, ret, 0, end - start );
Version[] ret = new Version[end - start];
System.arraycopy(values(), start, ret, 0, end - start);
return ret;
}
public boolean equalOrSamller(Version test){
public boolean equalOrSamller(Version test) {
return versionId(this) <= versionId(test);
}
......@@ -89,8 +92,8 @@ public enum Version {
public static Optional<Version> getPrevious(@NotNull final Version successorVersion) {
Version prevVersion = null;
for(Version version : values()) {
if(successorVersion.equals(version)) {
for (Version version : values()) {
if (successorVersion.equals(version)) {
return Optional.ofNullable(prevVersion);
}
prevVersion = version;
......@@ -98,7 +101,7 @@ public enum Version {
return Optional.empty();
}
@Override
public String toString() {
return label();
......
package org.vadere.simulator.projects.migration.helper;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Iterator;
import java.util.function.Predicate;
public class JsonFilterIterator implements Iterator<JsonNode> {
JsonNode root;
Predicate<JsonNode> filter;
Iterator<JsonNode> iter;
JsonNode next;
public JsonFilterIterator(JsonNode root, Predicate<JsonNode> filter) {
this.root = root;
this.filter = filter;
this.iter = root.iterator();
this.iter.hasNext();
}
/**
* Search for the next element in the wrapped iterator which evaluates the filter to true. Save
* this element as the next to serve and return true. Otherwise return false
*/
@Override
public boolean hasNext() {
while (iter.hasNext()) {
JsonNode n = iter.next();
if (filter.test(n)) {
this.next = n;
return true;
}
}
this.next = null;
return false;
}
/**
* use the next element and clean the element so it is not returned a second time.
*/
@Override
public JsonNode next() {
if (next == null) {
return null;
} else {
JsonNode tmp = next;
next = null;
return tmp;
}
}
}
......@@ -6,11 +6,13 @@ import org.vadere.annotation.factories.migrationassistant.MigrationTransformatio
import org.vadere.simulator.entrypoints.Version;
import org.vadere.simulator.projects.migration.MigrationException;
import java.util.Iterator;
@MigrationTransformation(targetVersionLabel = "0.5")
public class JoltTransformV4toV5 extends JoltTransformation {
public JoltTransformV4toV5() {
super(Version.V0_4);
super(Version.V0_5);
}
@Override
......@@ -20,11 +22,23 @@ public class JoltTransformV4toV5 extends JoltTransformation {
postTransformHooks.add(JoltTransformV1toV2::sort);
}
private JsonNode cleanupPedestrianOverlapProcessorAttribute(JsonNode node) throws MigrationException{
private JsonNode cleanupPedestrianOverlapProcessorAttribute(JsonNode node) throws MigrationException {
JsonNode processors = path(node, "processWriters/processors");
if (nodeIsArray(processors)) {
Iterator<JsonNode> iter = processors.iterator();
while (iter.hasNext()) {
JsonNode processor = iter.next();
String type = pathMustExist(processor, "type").asText();
if (type.equals("org.vadere.simulator.projects.dataprocessing.processor.PedestrianOverlapProcessor")) {
remove(processor, "attributes");
remove(processor, "attributesType");
}
}
}
return node;
}
private JsonNode addOverlapProcessors(JsonNode node) throws MigrationException{
private JsonNode addOverlapProcessors(JsonNode node) throws MigrationException {
return node;
}
......
......@@ -4,6 +4,7 @@ import com.bazaarvoice.jolt.Chainr;
import com.bazaarvoice.jolt.Diffy;
import com.bazaarvoice.jolt.JsonUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.log4j.Logger;
......@@ -17,8 +18,11 @@ import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
public abstract class JoltTransformation {
......@@ -47,34 +51,10 @@ public abstract class JoltTransformation {
} catch (ClassNotFoundException e) {
throw new MigrationException("Cannot find Transformation in Factory for Version " + currentVersion.nextVersion().label());
}
// String transformationResource = getTransforamtionResourcePath(currentVersion.label('-'), currentVersion.nextVersion().label('-'));
// String identityResource = getIdentiyResoucrePath(currentVersion.nextVersion().label('-'));
//
// JoltTransformation ret = transformations.getOrDefault(currentVersion, null);
// if ( ret == null) {
// switch (currentVersion) {
// case NOT_A_RELEASE:
// ret = new JoltTransformV0toV1(transformationResource, identityResource, currentVersion);
// break;
// case V0_1:
// ret = new JoltTransformV1toV2(transformationResource, identityResource, currentVersion);
// break;
// case V0_2:
// ret = new JoltTransformV2toV3(transformationResource, identityResource, currentVersion);
// break;
// case V0_3:
// ret = new JoltTransformV3toV4(transformationResource, identityResource, currentVersion);
// break;
// default:
// throw new MigrationException("No Transformation defined for Verson " + currentVersion.toString());
// }
// transformations.put(currentVersion, ret);
// }
return ret;
}
public static Path getTransforamtionFile(Version toVersion){
public static Path getTransforamtionFile(Version toVersion) {
String transformString = getTransforamtionResourcePath(
toVersion.previousVersion().label('-'),
toVersion.label('-'));
......@@ -87,7 +67,7 @@ public abstract class JoltTransformation {
return Paths.get(res);
}
public static Path getIdenityFile(Version v){
public static Path getIdenityFile(Version v) {
String idenityString = getIdentiyResoucrePath(v.label('-'));
URI res = null;
try {
......@@ -98,15 +78,15 @@ public abstract class JoltTransformation {
return Paths.get(res);
}
public static String getTransforamtionResourcePath(String from, String to){
return "/transform_v" +from.toUpperCase() + "_to_v" + to.toUpperCase() + ".json";
public static String getTransforamtionResourcePath(String from, String to) {
return "/transform_v" + from.toUpperCase() + "_to_v" + to.toUpperCase() + ".json";
}
public static String getIdentiyResoucrePath(String to){
public static String getIdentiyResoucrePath(String to) {
return "/identity_v" + to.toUpperCase() + ".json";
}
public JoltTransformation(String transformation, String identity) {
public JoltTransformation(String transformation, String identity) {
this.chainr = Chainr.fromSpec(JsonUtils.classpathToList(transformation));
this.identity = Chainr.fromSpec(JsonUtils.classpathToList(identity));
// Output of Transformation
......@@ -117,16 +97,16 @@ public abstract class JoltTransformation {
public JoltTransformation(Version targetVersion) {
this(getTransforamtionResourcePath(
targetVersion.previousVersion().label('-'),
targetVersion.label('-')),
getIdentiyResoucrePath(targetVersion.label('-')));
targetVersion.previousVersion().label('-'),
targetVersion.label('-')),
getIdentiyResoucrePath(targetVersion.label('-')));
}
public JsonNode applyTransformation(JsonNode root) throws MigrationException {
Object rootObject = StateJsonConverter.convertJsonNodeToObject(root);
rootObject = applyTransformation(rootObject);
JsonNode jsonRoot = StateJsonConverter.deserializeToNode(rootObject);
return applyPostHooks(jsonRoot);
return applyPostHooks(jsonRoot);
}
private Object applyTransformation(Object root) throws MigrationException {
......@@ -134,7 +114,7 @@ public abstract class JoltTransformation {
Object rootTransformedIdenity = identity.transform(rootTransformed);
Diffy.Result diffResult = diffy.diff(rootTransformed, rootTransformedIdenity);
if (diffResult.isEmpty()){
if (diffResult.isEmpty()) {
return rootTransformed;
} else {
logger.error("Error in Transformation " + diffResult.toString());
......@@ -142,7 +122,7 @@ public abstract class JoltTransformation {
}
}
public JsonNode applyPostHooks(JsonNode root) throws MigrationException{
public JsonNode applyPostHooks(JsonNode root) throws MigrationException {
JsonNode ret = root;
for (PostTransformHook hook : postTransformHooks) {
ret = hook.applyHook(ret);
......@@ -156,8 +136,8 @@ public abstract class JoltTransformation {
protected abstract void initPostHooks();
protected void addToObjectNode(JsonNode node, String key, String value){
((ObjectNode)node).put(key, value);
protected void addToObjectNode(JsonNode node, String key, String value) {
((ObjectNode) node).put(key, value);
}
......@@ -171,25 +151,26 @@ public abstract class JoltTransformation {
/**
* Create a Copy of Json and put nodes in user specified order
* @param target new LinkedHashMap with wherer to put nodes
* @param source source
* @param key key to add to new HashMap
* @param children Specify Order on second level
*
* @param target new LinkedHashMap with wherer to put nodes
* @param source source
* @param key key to add to new HashMap
* @param children Specify Order on second level
*/
protected static void putObject(LinkedHashMap<Object, Object> target,
LinkedHashMap<Object, Object> source,
String key, String... children) throws MigrationException {
LinkedHashMap<Object, Object> source,
String key, String... children) throws MigrationException {
Object obj = source.get(key);
if (obj == null) {
throw new MigrationException("Scenario must contain Key: " + key);
}
if (children.length > 0){
if (children.length > 0) {
LinkedHashMap<Object, Object> node = new LinkedHashMap<>();
LinkedHashMap<Object, Object> parent = (LinkedHashMap<Object, Object>) obj;
for (String childKey : children){
for (String childKey : children) {
Object childObj = parent.get(childKey);
if (childObj == null){
if (childObj == null) {
throw new MigrationException("Object with Key " + key + " does not has child with key" + childKey);
}
node.put(childKey, childObj);
......@@ -199,4 +180,53 @@ public abstract class JoltTransformation {
target.put(key, obj);
}
protected void remove(JsonNode root, String childName) throws MigrationException {
ObjectNode parent = (ObjectNode) root;
if (parent.remove(childName) == null) {
throw new MigrationException("Cannot delete childElement '" + childName + "' from parent " + root.asText());
}
}
protected JsonNode pathMustExist(JsonNode root, String path) throws MigrationException {
JsonNode ret = path(root, path);
if (ret.isMissingNode()) {
throw new MigrationException("Json Path Erro: The path '" + path +
"' should be accessible from " + root.asText());
}
return ret;
}
protected JsonNode path(JsonNode root, String path) {
String[] pathElements = path.split("/");
JsonNode ret = root;
for (String item : pathElements) {
ret = ret.path(item);
}
return ret;
}
protected boolean nodeIsArray(JsonNode node) {
return nodeNotEmptyAnd(node, n -> n.getNodeType() == JsonNodeType.ARRAY);
}
protected boolean nodeNotEmptyAnd(JsonNode node, Predicate<JsonNode> predicate) {
return !node.isMissingNode() && predicate.test(node);
}
protected Iterator<JsonNode> filterIterator(JsonNode root, Predicate<JsonNode> filter) {
return new Iterator<JsonNode>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public JsonNode next() {
return null;
}
};
}
}
......@@ -53,13 +53,6 @@
"attributes" : {
"pedestrianOverlapProcessorId" : 6
}
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianOverlapProcessor",
"id" : 6,
"attributesType" : "org.vadere.state.attributes.processor.AttributesPedestrianOverlapProcessor",
"attributes" : {
"pedRadius" : 0.2
}
} ],
"isTimestamped" : true
},
......
......@@ -16,7 +16,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class JoltTransformV0toV1Test extends JoltTransformationTest{
public class JoltTransformV0toV1Test extends JoltTransformationTest {
private final String TRANSFORM = "/transform_vNOT-A-RELEASE_to_v0.1.json";
private final String IDENTITY = "/identity_v0.1.json";
......@@ -32,11 +32,11 @@ public class JoltTransformV0toV1Test extends JoltTransformationTest{
public void TestPostHooks1() throws IOException, MigrationException, URISyntaxException {
JoltTransformation transformation = JoltTransformation.get(Version.NOT_A_RELEASE);
String TEST1 = "/migration/vNOT-A-RELEASE_to_v0.1_Test1.scenario";
JsonNode in = getJson(TEST1);
JsonNode in = getJsonFromResource(TEST1);
JsonNode out = transformation.applyTransformation(in);
// will test that sources exists.
JsonNode sources = pathMustExist(out, "vadere/topography/sources");
assertEquals("Therer must be one source",1, sources.size());
assertEquals("Therer must be one source", 1, sources.size());
assertTrue("The source should not have the attribute distributionParameters", sources.elements().next().path("distributionParameters").isMissingNode());
......@@ -54,11 +54,11 @@ public class JoltTransformV0toV1Test extends JoltTransformationTest{
public void TestPostHooks2() throws IOException, MigrationException, URISyntaxException {
JoltTransformation transformation = factory.getJoltTransformV0toV1();
String TEST2 = "/migration/vNOT-A-RELEASE_to_v0.1_Test2.scenario";
JsonNode in = getJson(TEST2);
JsonNode in = getJsonFromResource(TEST2);
JsonNode out = transformation.applyTransformation(in);
JsonNode sources = pathMustExist(out, "vadere/topography/sources");
assertEquals("Therer must be one source",1, sources.size());
assertEquals("Therer must be one source", 1, sources.size());
assertFalse("The source must have the attribute distributionParameters", sources.elements().next().path("distributionParameters").isMissingNode());
assertThat(pathMustExist(out, "vadere/mainModel"),
......@@ -75,7 +75,7 @@ public class JoltTransformV0toV1Test extends JoltTransformationTest{
public void TestPostHooks3() throws IOException, MigrationException, URISyntaxException {
JoltTransformation transformation = factory.getJoltTransformV0toV1();
String TEST3 = "/migration/vNOT-A-RELEASE_to_v0.1_Test3.scenario";
JsonNode in = getJson(TEST3);
JsonNode in = getJsonFromResource(TEST3);
transformation.applyTransformation(in);
fail("should not be reached! The Transformation should fail with MigrationException");
......
......@@ -12,7 +12,7 @@ import java.nio.file.Path;
import static org.junit.Assert.*;
public class JoltTransformV1toV2Test extends JoltTransformationTest{
public class JoltTransformV1toV2Test extends JoltTransformationTest {
private final String TRANSFORM = "/transform_v0.1_to_v0.2.json";
private final String IDENTITY = "/identity_v0.2.json";
......@@ -25,7 +25,7 @@ public class JoltTransformV1toV2Test extends JoltTransformationTest{
@Test
public void Test1() throws MigrationException, IOException, URISyntaxException {
JoltTransformation t = JoltTransformation.get(Version.V0_1);
JsonNode node = t.applyTransformation(getJson("/migration/v0.1_to_v0.2_Test1.scenario"));
JsonNode node = t.applyTransformation(getJsonFromResource("/migration/v0.1_to_v0.2_Test1.scenario"));
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesPotentialCompact");
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesOSM");
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesFloorField");
......@@ -35,8 +35,8 @@ public class JoltTransformV1toV2Test extends JoltTransformationTest{
@Test
public void Test2() throws MigrationException, IOException, URISyntaxException {
JoltTransformation t = JoltTransformation.get(Version.V0_1);
JsonNode node = t.applyTransformation(getJson("/migration/v0.1_to_v0.2_Test2.scenario"));
pathMustExist(node,"scenario/attributesModel/org.vadere.state.attributes.models.AttributesPotentialCompact");
JsonNode node = t.applyTransformation(getJsonFromResource("/migration/v0.1_to_v0.2_Test2.scenario"));
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesPotentialCompact");
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesOSM");
pathMustExist(node, "scenario/attributesModel/org.vadere.state.attributes.models.AttributesFloorField");
......@@ -46,7 +46,7 @@ public class JoltTransformV1toV2Test extends JoltTransformationTest{
@Test
public void Test3() throws MigrationException, IOException, URISyntaxException {
JoltTransformation t = JoltTransformation.get(Version.V0_1);
JsonNode node = t.applyTransformation(getJson("/migration/v0.1_to_v0.2_Test3.scenario"));
JsonNode node = t.applyTransformation(getJsonFromResource("/migration/v0.1_to_v0.2_Test3.scenario"));
pathMustExist(node, "scenario/attributesModel");
assertEquals("should be empty", 0, pathMustExist(node, "scenario/attributesModel").size());
assertThat(pathMustExist(node, "name"), nodeHasText("XXXX"));
......
package org.vadere.simulator.projects.migration.jolttranformation;
import com.fasterxml.jackson.databind.JsonNode;
import org.vadere.simulator.entrypoints.Version;
import org.junit.Test;
import org.vadere.simulator.projects.migration.MigrationException;
import org.vadere.simulator.projects.migration.helper.JsonFilterIterator;
import java.nio.file.Path;
import java.util.Iterator;
import static org.junit.Assert.*;
......@@ -12,4 +21,84 @@ public class JoltTransformV4toV5Test extends JoltTransformationTest {
return getDirFromResources("/migration/v04_to_v05");
}
private JsonNode test001() {
String test001 = getTestFileAsString("test001.scenario");
assertThat(test001, versionMatcher(Version.V0_4));
return getJsonFromString(test001);
}
private JsonNode test002() {
String test002 = getTestFileAsString("test002.scenario");
assertThat(test002, versionMatcher(Version.V0_4));
return getJsonFromString(test002);