Hector
Hector

Reputation: 5418

How to Store data in graphs using Inheritance with GraphStream

In the GraphStream tutorial titled

Storing, retrieving and displaying data in graphs

it states:-

Other ways to store data on graphs
Sometimes you want to create your own graph structure and inherit the Node and Edge classes to create your own. In this case you will probably not store the data under the form of key-value attributes but inside fields of the classes you define. Both ways, key-value or inheritance, have their advantages and drawbacks.

I am attempting to employ inheritance (by extending org.graphstream.graph.implementations.SingleNode)

My code tests fail with

org.graphstream.graph.ElementNotFoundException

I create two custom "DataNode"s as follows:-

final Node dataNode1 = DataNode.builder().graph(GRAPH).id("One").stringData("StringData_1").integerData(1).build();
final Node dataNode2 = DataNode.builder().graph(GRAPH).id("Two").stringData("StringData_2").integerData(2).build();

Then attempt to create an "edge" between them...

GRAPH.addEdge("Some", dataNode1, dataNode2);

My graph is defined as follows:-

private static final SingleGraph GRAPH = new SingleGraph("Data");

Which is configured as follows:-

GRAPH.setStrict(false);
GRAPH.setAutoCreate(true);
GRAPH.addAttribute("ui.quality");
GRAPH.addAttribute("ui.antialias");

How do you employ inheritance to store custom data attributes with

// https://mvnrepository.com/artifact/org.graphstream/gs-core
compile group: 'org.graphstream', name: 'gs-core', version: '1.3'
// https://mvnrepository.com/artifact/org.graphstream/gs-ui
compile group: 'org.graphstream', name: 'gs-ui', version: '1.3'

My DataNode class resembles:-

public class DataNode extends SingleNode {

    private final String mStringData;
    private final Integer mIntegerData;

    public DataNode(final AbstractGraph graph, final String id, final Builder builder) {
        super(graph, id);
        this.mStringData = builder.getStringData();
        this.mIntegerData = builder.getIntegerData();
    }

    /**
     * @return the mStringData
     */
    public String getStringData() {
        return mStringData;
    }

    /**
     * @return the mIntegerData
     */
    public Integer getIntegerData() {
        return mIntegerData;
    }

    public static Builder builder() {

        return new Builder();
    }

    public static class Builder {

        private AbstractGraph graph;
        private String id;

        private String mStringData;
        private Integer mIntegerData;

        /**
         * @param graph
         *            the graph to set
         */
        public Builder graph(final AbstractGraph graph) {
            this.graph = graph;
            return this;
        }

        /**
         * @param id
         *            the id to set
         */
        public Builder id(final String id) {
            this.id = id;
            return this;
        }

        /**
         * @param mStringData
         *            the mStringData to set
         */
        public Builder stringData(final String mStringData) {
            this.mStringData = mStringData;
            return this;
        }

        /**
         * @param mIntegerData
         *            the mIntegerData to set
         */
        public Builder integerData(final Integer mIntegerData) {
            this.mIntegerData = mIntegerData;
            return this;
        }

        /**
         * @return the graph
         */
        public AbstractGraph getGraph() {
            return graph;
        }

        /**
         * @return the id
         */
        public String getId() {
            return id;
        }

        /**
         * @return the mStringData
         */
        public String getStringData() {
            return mStringData;
        }

        /**
         * @return the mIntegerData
         */
        public Integer getIntegerData() {
            return mIntegerData;
        }

        public DataNode build() {
            return new DataNode(graph, id, this);
        }
    }
}

Upvotes: 1

Views: 373

Answers (1)

Yoann
Yoann

Reputation: 566

If you don't absolutely need the string and integer fields of your node subclass to be final then you can set a new node factory for the graph.

Your extended Node would be simpler:

class DataNode extends SingleNode {
    private  String mStringData;
    private  Integer mIntegerData;
    public DataNode( AbstractGraph graph, final String id) {
        super(graph, id);
    }
    public void setStringData(String mStringData) {
        this.mStringData = mStringData;
    }
    public void setIntegerData(Integer mIntegerData) {
        this.mIntegerData = mIntegerData;
    }
    public String getStringData() {
        return mStringData;
    }
    public Integer getIntegerData() {
        return mIntegerData;
    }
}

Then you can use a node factory:

GRAPH.setNodeFactory(new NodeFactory<Node>() {
    @Override
    public Node newInstance(String id, Graph graph) {
        return new DataNode((AbstractGraph) graph, id);
    }
});

or the java 8 version:

GRAPH.setNodeFactory((id, graph) -> new DataNode((AbstractGraph)graph, id));

finally create nodes and then set the attributes (that's why they can't be final):

final Node dataNode1 = GRAPH.addNode("One");
((DataNode)dataNode1).setStringData("StringData_1");
((DataNode)dataNode1).setIntegerData(1);

final Node dataNode2 = GRAPH.addNode("Twi");
((DataNode)dataNode1).setStringData("StringData_2");
((DataNode)dataNode1).setIntegerData(2);

GRAPH.addEdge("Some", dataNode1, dataNode2);

Upvotes: 1

Related Questions