daniel9x
daniel9x

Reputation: 805

JGraphT: How to use JSONImporter to Import my DirectedMultigraph with Labeled Edges

I have created a custom edge class as defined here. The only change I made was a No Arg constructor in order to get the import code below to run. I have successfully generated a DirectedMultigraph via the JSONExporter class and now want to take that exported JSON and re-import it via the JSONImporter class.

I'm having trouble doing this and retaining my edge labels due to my limited understanding of how to build the EdgeProvider required for my JSONImporter constructor.

This is the JSON I'm trying to import:

{
  "edges": [
    {
      "id": "{shipmentNumber:12345}",
      "source": "DEHAM",
      "target": "USNYC"
    }
  ],
  "nodes": [
    {
      "id": "DEHAM"
    },
    {
      "id": "USNYC"
    }
  ],
  "creator": "JGraphT JSON Exporter",
  "version": "1"
}

This is the code that I have so far:

Graph<String, RelationshipEdge> graph = new DirectedMultigraph<>(SupplierUtil.createStringSupplier(), SupplierUtil.createSupplier(RelationshipEdge.class), false);

VertexProvider<String> vertexProvider = (label, attributes) -> label;

EdgeProvider<String, RelationshipEdge> edgeProvider =
              (from, to, label, attributes) -> graph.getEdgeSupplier().get();

JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);

importer.importGraph(graph, new StringReader([inputJSON]);

I know the problem is the EdgeProvider assignment because I don't know how to pass the argument constructor for the RelationshipEdge class which is where the actual label is set. If I could figure out how to call the argument constructor of the RelationshipEdge class then I think that would solve my problem.

FYI, this is my JSONExporter Code:

ComponentNameProvider<String> vertexIdProvider = name -> name;
ComponentNameProvider<RelationshipEdge> edgeLabelProvider = component -> component.getLabel();
ComponentAttributeProvider<String> vertexAttributeProvider = component -> new HashMap<>();
ComponentAttributeProvider<RelationshipEdge> edgeAttributeProvider = component -> new HashMap<>();


GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>(vertexIdProvider, vertexAttributeProvider, edgeLabelProvider, edgeAttributeProvider);
StringWriter writer = new StringWriter();
jsonExporter.exportGraph(graph, writer);
System.out.println(writer.toString());

The following JSON is exported (with the label/id missing):

{
  "creator": "JGraphT JSON Exporter",
  "version": "1",
  "nodes": [
    {
      "id": "DEHAM"
    },
    {
      "id": "USNYC"
    }
  ],
  "edges": [
    {
      "source": "DEHAM",
      "target": "USNYC"
    }
  ]
}

Upvotes: 0

Views: 1285

Answers (1)

Arcanefoam
Arcanefoam

Reputation: 727

Since your graph is using the SupplierUtil factory methods, the graph importer will use no-arg constructors as it visits/parses the json file, iterates over all the nodes/edges in the file and creates instances for them. In order to set your node/edge attributes during import you need to provide appropriate Vertex/Edge Attribute Consumers to the importer. Additionally, your node/edge classes need methods to access/modify their attributes:

JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);
importer.addEdgeAttributeConsumer((edgeField, value) -> {
  // edgeField: Pair<Edge, String> / Edge instance, field name
  // value: instance of org.jgrapht.nio.Attribute / getValue(); getType();
  RelationshipEdge = edgeField.getFirst();
  e.setLabel(value.getValue());  // Note that since you only have one field I am not finding the
                                 // correct setter. I don't like reflection so I would probably
                                 // add a 'setField(name, value)' method to my edge/node implementation.
    });

To persist your graph, the idea is the same. But in this case you need Vertex/Edge AttributeProviders (You added them but they always returned empty maps):

GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>();
exporter.setEdgeAttributeProvider(e -> {
            Map<String, Attribute> attribs = new HashMap<>();
            attribs.put("label", new DefaultAttribute<String>(e.getLabel(), AttributeType.STRING));
            return attribs;
        });

Upvotes: 1

Related Questions