diff --git a/graphs-core/src/main/java/com/github/moaxcp/graphs/AbstractPropertyGraph.java b/graphs-core/src/main/java/com/github/moaxcp/graphs/AbstractPropertyGraph.java index c5bb2f9..494940c 100644 --- a/graphs-core/src/main/java/com/github/moaxcp/graphs/AbstractPropertyGraph.java +++ b/graphs-core/src/main/java/com/github/moaxcp/graphs/AbstractPropertyGraph.java @@ -14,6 +14,7 @@ * * @param type of all identifiers in graph */ +@ToString(exclude = {"edgeIds", "adjacentEdges", "inEdges", "outEdges"}) public abstract class AbstractPropertyGraph implements PropertyGraph { private LocalProperties properties; private LocalProperties vertexProperties; diff --git a/graphs-core/src/main/java/com/github/moaxcp/graphs/EdgeKey.java b/graphs-core/src/main/java/com/github/moaxcp/graphs/EdgeKey.java index ad18c9f..a812753 100644 --- a/graphs-core/src/main/java/com/github/moaxcp/graphs/EdgeKey.java +++ b/graphs-core/src/main/java/com/github/moaxcp/graphs/EdgeKey.java @@ -1,6 +1,6 @@ package com.github.moaxcp.graphs; -import static java.util.Objects.*; +import static java.util.Objects.requireNonNull; /** * Key for identifying edges within a collection such as Map. Extensions of this class define how two edges are equal diff --git a/graphs-core/src/main/java/com/github/moaxcp/graphs/LocalProperties.java b/graphs-core/src/main/java/com/github/moaxcp/graphs/LocalProperties.java index 1663246..46bf405 100644 --- a/graphs-core/src/main/java/com/github/moaxcp/graphs/LocalProperties.java +++ b/graphs-core/src/main/java/com/github/moaxcp/graphs/LocalProperties.java @@ -12,6 +12,7 @@ * can never be set as null. */ @ToString +@EqualsAndHashCode class LocalProperties { private final Map local = new LinkedHashMap<>(); diff --git a/graphs-core/src/test/java/com/github/moaxcp/graphs/EqualsTest.java b/graphs-core/src/test/java/com/github/moaxcp/graphs/EqualsTest.java index 0a9f980..8893ba4 100644 --- a/graphs-core/src/test/java/com/github/moaxcp/graphs/EqualsTest.java +++ b/graphs-core/src/test/java/com/github/moaxcp/graphs/EqualsTest.java @@ -4,7 +4,20 @@ import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; +import static com.google.common.truth.Truth.assertThat; + public class EqualsTest { + + @Test + void undirectedEmpty() { + assertThat(new UndirectedPropertyGraph<>()).isEqualTo(new UndirectedPropertyGraph<>()); + } + + @Test + void directedEmpty() { + assertThat(new DirectedPropertyGraph<>()).isEqualTo(new DirectedPropertyGraph<>()); + } + @Test void undirected() { EqualsVerifier diff --git a/graphs-jackson-modules/build.gradle b/graphs-jackson-modules/build.gradle new file mode 100644 index 0000000..3d58e91 --- /dev/null +++ b/graphs-jackson-modules/build.gradle @@ -0,0 +1,102 @@ +plugins { + id 'maven-publish' + id 'signing' +} + +description = 'jackson modules for serialization' + +modularity.patchModule('truth', 'truth-java8-extension-1.1.3.jar') +modularity.patchModule('jsonassert', 'android-json-0.0.20131108.vaadin1.jar') + +publishing { + publications { + mavenJava(MavenPublication) { + groupId = 'com.github.moaxcp.graphs' + artifactId = project.name + from components.java + artifact sourcesJar + artifact javadocJar + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + name = project.name + description = project.description + url = 'https://github.com/moaxcp/graphs' + licenses { + license { + name = 'The MIT License (MIT)' + url = 'http://opensource.org/licenses/MIT' + } + } + developers { + developer { + id = 'moaxcp' + name = 'John Mercier' + email = 'moaxcp@gmail.com' + } + } + scm { + connection = 'scm:git:git://github.com/moaxcp/graphs.git' + developerConnection = 'scm:git:git@github.com:moaxcp/graphs.git' + url = 'https://github.com/moaxcp/graphs' + } + } + repositories { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/moaxcp/graphs") + credentials { + username = project.findProperty('github.user') + password = project.findProperty('github.key') + } + } + } + } + } +} + +signing { + sign publishing.publications.mavenJava +} + +jacocoTestReport { + dependsOn ':graphs-test:test' + executionData("${project(':graphs-test').buildDir}/jacoco/test.exec") +} + +sonarqube { + properties { + property "sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/test/jacocoTestReport.xml,${project(':graphs-test').buildDir}/reports/jacoco/test/jacocoTestReport.xml" + } +} + +compileTestJava { + moduleOptions { + addReads = [ + 'com.github.moaxcp.graphs.jackson' : 'truth,org.junit.jupiter.params,jsonassert' + ] + + addModules = ['truth', 'org.junit.jupiter.params', 'jsonassert'] + } +} + +test { + moduleOptions { + addReads = [ + 'com.github.moaxcp.graphs.jackson' : 'truth,org.junit.jupiter.params,jsonassert' + ] + } +} + + +dependencies { + api project(':graphs-core') + api 'com.fasterxml.jackson.core:jackson-databind:2.14.2' + testImplementation 'org.skyscreamer:jsonassert:1.5.1' +} \ No newline at end of file diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/DirectedPropertyGraphDeserializer.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/DirectedPropertyGraphDeserializer.java new file mode 100644 index 0000000..43c3c84 --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/DirectedPropertyGraphDeserializer.java @@ -0,0 +1,19 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.github.moaxcp.graphs.DirectedPropertyGraph; +import java.io.IOException; + +public class DirectedPropertyGraphDeserializer extends StdDeserializer> { + protected DirectedPropertyGraphDeserializer() { + super(DirectedPropertyGraph.class); + } + + @Override + public DirectedPropertyGraph deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + return new DirectedPropertyGraph<>(); + } +} diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphDeserializers.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphDeserializers.java new file mode 100644 index 0000000..543b3d0 --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphDeserializers.java @@ -0,0 +1,20 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.deser.Deserializers; +import com.github.moaxcp.graphs.DirectedPropertyGraph; +import com.github.moaxcp.graphs.UndirectedPropertyGraph; + +public class GraphDeserializers extends Deserializers.Base { + + @Override + public JsonDeserializer findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException { + if(type.hasRawClass(DirectedPropertyGraph.class)) { + return new DirectedPropertyGraphDeserializer(); + } + if(type.hasRawClass(UndirectedPropertyGraph.class)) { + return new UndirectedPropertyGraphDeserializer(); + } + return super.findBeanDeserializer(type, config, beanDesc); + } +} diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphSerializers.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphSerializers.java new file mode 100644 index 0000000..62995ea --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphSerializers.java @@ -0,0 +1,19 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.ser.Serializers; +import com.github.moaxcp.graphs.PropertyGraph; + +public class GraphSerializers extends Serializers.Base { + @Override + public JsonSerializer findSerializer(SerializationConfig config, JavaType type, BeanDescription beanDesc) { + Class raw = type.getRawClass(); + if (PropertyGraph.class.isAssignableFrom(raw)) { + return PropertyGraphSerializer.INSTANCE; + } + return super.findSerializer(config, type, beanDesc); + } +} diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphsModule.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphsModule.java new file mode 100644 index 0000000..9f85c15 --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/GraphsModule.java @@ -0,0 +1,23 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.core.json.PackageVersion; +import com.fasterxml.jackson.databind.Module; + +public class GraphsModule extends Module { + @Override + public String getModuleName() { + return "GraphsModule"; + } + + @Override + public Version version() { + return PackageVersion.VERSION; + } + + @Override + public void setupModule(SetupContext context) { + context.addDeserializers(new GraphDeserializers()); + context.addSerializers(new GraphSerializers()); + } +} diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/PropertyGraphSerializer.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/PropertyGraphSerializer.java new file mode 100644 index 0000000..2e9db3e --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/PropertyGraphSerializer.java @@ -0,0 +1,62 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.github.moaxcp.graphs.PropertyGraph; +import com.github.moaxcp.graphs.PropertyGraph.Edge; +import com.github.moaxcp.graphs.PropertyGraph.Vertex; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class PropertyGraphSerializer extends StdSerializer { + + static final PropertyGraphSerializer INSTANCE = new PropertyGraphSerializer(); + protected PropertyGraphSerializer() { + super(PropertyGraph.class); + } + + @Override + public void serialize(PropertyGraph value, JsonGenerator gen, SerializerProvider provider) throws IOException { + gen.writeStartObject(); + serializeCheckEmptyMap("properties", value.getProperties(), gen, provider); + serializeCheckEmptyMap("vertexProperties", value.getVertexProperties(), gen, provider); + serializeCheckEmptyMap("edgeProperties", value.getEdgeProperties(), gen, provider); + serializeVertices(value.getVertices(), gen, provider); + serializeEdges(value.getEdges(), gen, provider); + gen.writeEndObject(); + } + + private void serializeEdges(Collection edges, JsonGenerator gen, SerializerProvider provider) throws IOException { + serializeCheckEmptyList("edges", edges.stream().map(e -> (Map) e.local()).toList(), gen, provider); + } + + private void serializeVertices(Map vertices, JsonGenerator gen, SerializerProvider provider) throws IOException { + List> collect = vertices.values().stream() + .filter(v -> !(v.adjacentEdges().size() > 0 && v.local().size() == 1)) + .map(v -> (Map) v.local()) + .toList(); + serializeCheckEmptyList("vertices", collect, gen, provider); + } + + private void serializeCheckEmptyList(String name, List> value, JsonGenerator gen, SerializerProvider provider) throws IOException { + if (value.isEmpty() && !(provider.getConfig().getDefaultPropertyInclusion().getContentInclusion().equals(Include.NON_EMPTY) + || provider.getConfig().getDefaultPropertyInclusion().getContentInclusion().equals(Include.NON_NULL))) { + provider.defaultSerializeField(name, null, gen); + } else if (!value.isEmpty()) { + provider.defaultSerializeField(name, value, gen); + } + } + + private void serializeCheckEmptyMap(String name, Map value, JsonGenerator gen, SerializerProvider provider) throws IOException { + if (value.isEmpty() && !(provider.getConfig().getDefaultPropertyInclusion().getContentInclusion().equals(Include.NON_EMPTY) + || provider.getConfig().getDefaultPropertyInclusion().getContentInclusion().equals(Include.NON_NULL))) { + provider.defaultSerializeField(name, null, gen); + } else if (!value.isEmpty()) { + provider.defaultSerializeField(name, value, gen); + } + } +} diff --git a/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/UndirectedPropertyGraphDeserializer.java b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/UndirectedPropertyGraphDeserializer.java new file mode 100644 index 0000000..f249aba --- /dev/null +++ b/graphs-jackson-modules/src/main/java/com/github/moaxcp/graphs/jackson/UndirectedPropertyGraphDeserializer.java @@ -0,0 +1,21 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.github.moaxcp.graphs.UndirectedPropertyGraph; +import java.io.IOException; + +public class UndirectedPropertyGraphDeserializer extends StdDeserializer> { + protected UndirectedPropertyGraphDeserializer() { + super(UndirectedPropertyGraph.class); + } + + @Override + public UndirectedPropertyGraph deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + p. + return new UndirectedPropertyGraph<>(); + } +} diff --git a/graphs-jackson-modules/src/main/java/module-info.java b/graphs-jackson-modules/src/main/java/module-info.java new file mode 100644 index 0000000..51ecd7d --- /dev/null +++ b/graphs-jackson-modules/src/main/java/module-info.java @@ -0,0 +1,5 @@ +module com.github.moaxcp.graphs.jackson { + requires transitive com.github.moaxcp.graphs.core; + requires transitive com.fasterxml.jackson.databind; + exports com.github.moaxcp.graphs.jackson; +} \ No newline at end of file diff --git a/graphs-jackson-modules/src/main/resources/META-INF/services/com.github.moaxcp.graphs.jackson.GraphsModule b/graphs-jackson-modules/src/main/resources/META-INF/services/com.github.moaxcp.graphs.jackson.GraphsModule new file mode 100644 index 0000000..697a02c --- /dev/null +++ b/graphs-jackson-modules/src/main/resources/META-INF/services/com.github.moaxcp.graphs.jackson.GraphsModule @@ -0,0 +1 @@ +com.github.moaxcp.graphs.jackson.GraphsModule \ No newline at end of file diff --git a/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphDeserializeTest.java b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphDeserializeTest.java new file mode 100644 index 0000000..658352e --- /dev/null +++ b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphDeserializeTest.java @@ -0,0 +1,47 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.moaxcp.graphs.DirectedPropertyGraph; +import com.github.moaxcp.graphs.UndirectedPropertyGraph; + +import static com.google.common.truth.Truth.assertThat; + +public class GraphDeserializeTest { + + @InclusionMapperTest + void emptyGraphDirected(ObjectMapper mapper) throws JsonProcessingException { + var result = mapper.readValue("{}", DirectedPropertyGraph.class); + assertThat(result).isEqualTo(new DirectedPropertyGraph()); + } + + @InclusionMapperTest + void emptyGraphUndirected(ObjectMapper mapper) throws JsonProcessingException { + var result = mapper.readValue("{}", UndirectedPropertyGraph.class); + assertThat(result).isEqualTo(new UndirectedPropertyGraph()); + } + + @InclusionMapperTest + void graphWithIdDirected(ObjectMapper mapper) throws JsonProcessingException { + var result = mapper.readValue(""" + { + "properties" : { + "id": "graph" + } + } + """, DirectedPropertyGraph.class); + assertThat(result).isEqualTo(new DirectedPropertyGraph().id("graph")); + } + + @InclusionMapperTest + void graphWithIdUndirected(ObjectMapper mapper) throws JsonProcessingException { + var result = mapper.readValue(""" + { + "properties" : { + "id": "graph" + } + } + """, UndirectedPropertyGraph.class); + assertThat(result).isEqualTo(new UndirectedPropertyGraph().id("graph")); + } +} diff --git a/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphSerializeTest.java b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphSerializeTest.java new file mode 100644 index 0000000..51ef1fe --- /dev/null +++ b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/GraphSerializeTest.java @@ -0,0 +1,279 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.moaxcp.graphs.DirectedPropertyGraph; +import com.github.moaxcp.graphs.PropertyGraph; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; + +import static com.github.moaxcp.graphs.jackson.MethodSources.mapper; + +public class GraphSerializeTest { + + @InclusionMapperWithGraphTest + void emptyGraphSerialize(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals("{}", result, JSONCompareMode.STRICT); + } + + @Test + void emptyGraph() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>(); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties": null, + "vertexProperties": null, + "edgeProperties": null, + "vertices": null, + "edges": null + } + """, result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithId(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph.id("graph"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties" : { + "id": "graph" + } + } + """, + result, JSONCompareMode.STRICT); + } + + @Test + void graphWithId() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>().id("graph"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties" : { + "id": "graph" + }, + "vertexProperties": null, + "edgeProperties": null, + "vertices": null, + "edges": null + } + """, + result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithIdAndProperties(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph.id("graph").property("k1", "v1").property("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties" : { + "id": "graph", + "k1": "v1", + "k2": "v2" + } + } + """, + result, JSONCompareMode.STRICT); + } + + @Test + void graphWithIdAndProperties() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>().id("graph").property("k1", "v1").property("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties" : { + "id": "graph", + "k1": "v1", + "k2": "v2" + }, + "vertexProperties": null, + "edgeProperties": null, + "vertices": null, + "edges": null + } + """, + result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithVertexProperties(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph.vertexProperty("k1", "v1").vertexProperty("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "vertexProperties" : { + "k1": "v1", + "k2": "v2" + } + } + """, + result, JSONCompareMode.STRICT); + } + + @Test + void graphWithVertexProperties() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>().vertexProperty("k1", "v1").vertexProperty("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties": null, + "vertexProperties" : { + "k1": "v1", + "k2": "v2" + }, + "edgeProperties": null, + "vertices": null, + "edges": null + } + """, + result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithEdgeProperties(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph.edgeProperty("k1", "v1").edgeProperty("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "edgeProperties" : { + "k1": "v1", + "k2": "v2" + } + } + """, + result, JSONCompareMode.STRICT); + } + + @Test + void graphWithEdgeProperties() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>().edgeProperty("k1", "v1").edgeProperty("k2", "v2"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties": null, + "vertexProperties": null, + "edgeProperties" : { + "k1": "v1", + "k2": "v2" + }, + "vertices": null, + "edges": null + } + """, + result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithVertex(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph.vertex("A"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "vertices" : [ + { + "id": "A" + } + ] + } + """, + result, JSONCompareMode.STRICT); + } + + @Test + void graphWithVertex() throws JsonProcessingException, JSONException { + var graph = new DirectedPropertyGraph<>().vertex("A"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties": null, + "vertexProperties": null, + "edgeProperties": null, + "vertices" : [ + { + "id": "A" + } + ], + "edges": null + } + """, + result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithEdge(ObjectMapper mapper, PropertyGraph graph) throws JSONException, JsonProcessingException { + graph.edge("A", "B"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "edges" : [ + { + "source": "A", + "target": "B" + } + ] + } + """, result, JSONCompareMode.STRICT); + } + + @Test + void graphWithEdge() throws JSONException, JsonProcessingException { + var graph = new DirectedPropertyGraph<>().edge("A", "B"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties": null, + "vertexProperties": null, + "edgeProperties": null, + "edges" : [ + { + "source": "A", + "target": "B" + } + ], + "vertices": null + } + """, result, JSONCompareMode.STRICT); + } + + @InclusionMapperWithGraphTest + void graphWithEverything(ObjectMapper mapper, PropertyGraph graph) throws JsonProcessingException, JSONException { + graph + .edge("A", "B", "prop1", "value1", "prop2", "value2") + .vertex("C") + .vertex("A", "k1", "v1") + .edgeProperty("edgeProp", "edgeValue") + .vertexProperty("vertexProp", "vertexValue") + .property("graphProperty", "graphValue") + .id("graphId"); + graph.getEdge("A", "B").id("edgeId"); + var result = mapper.writeValueAsString(graph); + JSONAssert.assertEquals(""" + { + "properties":{ + "graphProperty":"graphValue", + "id":"graphId" + }, + "vertexProperties": { + "vertexProp":"vertexValue" + }, + "edgeProperties": { + "edgeProp":"edgeValue" + }, + "vertices": [ + {"id":"A","k1":"v1"}, + {"id":"C"} + ], + "edges": [ + {"prop1":"value1","prop2":"value2","source":"A","target":"B","id":"edgeId"} + ] + } + """, result, JSONCompareMode.STRICT); + } +} diff --git a/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperTest.java b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperTest.java new file mode 100644 index 0000000..d3639ec --- /dev/null +++ b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperTest.java @@ -0,0 +1,12 @@ +package com.github.moaxcp.graphs.jackson; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@Retention(RetentionPolicy.RUNTIME) +@ParameterizedTest +@MethodSource("com.github.moaxcp.graphs.jackson.MethodSources#inclusionMappers") +public @interface InclusionMapperTest { +} diff --git a/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperWithGraphTest.java b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperWithGraphTest.java new file mode 100644 index 0000000..f6b31a5 --- /dev/null +++ b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/InclusionMapperWithGraphTest.java @@ -0,0 +1,12 @@ +package com.github.moaxcp.graphs.jackson; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@Retention(RetentionPolicy.RUNTIME) +@ParameterizedTest +@MethodSource("com.github.moaxcp.graphs.jackson.MethodSources#mappersToGraphs") +public @interface InclusionMapperWithGraphTest { +} diff --git a/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/MethodSources.java b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/MethodSources.java new file mode 100644 index 0000000..6a7390e --- /dev/null +++ b/graphs-jackson-modules/src/test/java/com/github/moaxcp/graphs/jackson/MethodSources.java @@ -0,0 +1,23 @@ +package com.github.moaxcp.graphs.jackson; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.moaxcp.graphs.DirectedPropertyGraph; +import com.github.moaxcp.graphs.UndirectedPropertyGraph; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.params.provider.Arguments; + +public class MethodSources { + + public static ObjectMapper mapper = new ObjectMapper().registerModule(new GraphsModule()); + + public static Stream inclusionMappers() { + return List.of(new ObjectMapper().registerModule(new GraphsModule()).setDefaultPropertyInclusion(Include.NON_EMPTY), + new ObjectMapper().registerModule(new GraphsModule()).setDefaultPropertyInclusion(Include.NON_NULL)).stream(); + } + + public static Stream mappersToGraphs() { + return inclusionMappers().flatMap(mapper -> Stream.of(Arguments.of(mapper, new DirectedPropertyGraph()), Arguments.of(mapper, new UndirectedPropertyGraph()))); + } +} diff --git a/settings.gradle b/settings.gradle index e9f5937..2e579d1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,6 +9,7 @@ rootProject.name = 'graphs' include 'graphs-core' +include 'graphs-jackson-modules' include 'graphs-test' include 'graphs-truth' include 'graphs-graphviz'