Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*
* @param <ID> type of all identifiers in graph
*/
@ToString(exclude = {"edgeIds", "adjacentEdges", "inEdges", "outEdges"})
public abstract class AbstractPropertyGraph<ID> implements PropertyGraph<ID> {
private LocalProperties properties;
private LocalProperties vertexProperties;
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* can never be set as null.
*/
@ToString
@EqualsAndHashCode
class LocalProperties {
private final Map<String, Object> local = new LinkedHashMap<>();

Expand Down
13 changes: 13 additions & 0 deletions graphs-core/src/test/java/com/github/moaxcp/graphs/EqualsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
102 changes: 102 additions & 0 deletions graphs-jackson-modules/build.gradle
Original file line number Diff line number Diff line change
@@ -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 = '[email protected]'
}
}
scm {
connection = 'scm:git:git://github.com/moaxcp/graphs.git'
developerConnection = 'scm:git:[email protected]: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'
}
Original file line number Diff line number Diff line change
@@ -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<DirectedPropertyGraph<?>> {
protected DirectedPropertyGraphDeserializer() {
super(DirectedPropertyGraph.class);
}

@Override
public DirectedPropertyGraph<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
return new DirectedPropertyGraph<>();
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
@@ -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<PropertyGraph> {

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<Edge> edges, JsonGenerator gen, SerializerProvider provider) throws IOException {
serializeCheckEmptyList("edges", edges.stream().map(e -> (Map<String, Object>) e.local()).toList(), gen, provider);
}

private void serializeVertices(Map<Object, Vertex> vertices, JsonGenerator gen, SerializerProvider provider) throws IOException {
List<Map<String, Object>> collect = vertices.values().stream()
.filter(v -> !(v.adjacentEdges().size() > 0 && v.local().size() == 1))
.map(v -> (Map<String, Object>) v.local())
.toList();
serializeCheckEmptyList("vertices", collect, gen, provider);
}

private void serializeCheckEmptyList(String name, List<Map<String, Object>> 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<String, Object> 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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<UndirectedPropertyGraph<?>> {
protected UndirectedPropertyGraphDeserializer() {
super(UndirectedPropertyGraph.class);
}

@Override
public UndirectedPropertyGraph<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
p.
return new UndirectedPropertyGraph<>();
}
}
5 changes: 5 additions & 0 deletions graphs-jackson-modules/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.github.moaxcp.graphs.jackson.GraphsModule
Original file line number Diff line number Diff line change
@@ -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<String>());
}

@InclusionMapperTest
void emptyGraphUndirected(ObjectMapper mapper) throws JsonProcessingException {
var result = mapper.readValue("{}", UndirectedPropertyGraph.class);
assertThat(result).isEqualTo(new UndirectedPropertyGraph<String>());
}

@InclusionMapperTest
void graphWithIdDirected(ObjectMapper mapper) throws JsonProcessingException {
var result = mapper.readValue("""
{
"properties" : {
"id": "graph"
}
}
""", DirectedPropertyGraph.class);
assertThat(result).isEqualTo(new DirectedPropertyGraph<String>().id("graph"));
}

@InclusionMapperTest
void graphWithIdUndirected(ObjectMapper mapper) throws JsonProcessingException {
var result = mapper.readValue("""
{
"properties" : {
"id": "graph"
}
}
""", UndirectedPropertyGraph.class);
assertThat(result).isEqualTo(new UndirectedPropertyGraph<String>().id("graph"));
}
}
Loading