Passed
Push — master ( 835cc2...027776 )
by Kolja
01:16
created

jgfJsonDecorator.js ➔ ... ➔ ???   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
const _ = require('deepdash')(require('lodash'));
2
const check = require('check-types');
3
const { JgfNode } = require('./jgfNode');
4
const { JgfEdge } = require('./jgfEdge');
5
const { JgfGraph } = require('./jgfGraph');
6
const { JgfMultiGraph } = require('./jgfMultiGraph');
7
8
/**
9
 * Transforms graphs or multigraphs to json or vice versa.
10
 *
11
 * Note that this is just called decorator for semantic reasons and does not follow the GoF decorator design pattern.
12
 */
13
class JgfJsonDecorator {
14
15
    /**
16
     * Creates a JGF graph or multigraph from JSON.
17
     * @param {object} json
18
     * @returns {JgfGraph,JgfMultiGraph}
19
     */
20
    static fromJson(json) {
21
        if (check.assigned(json.graph)) {
22
            return this._graphFromJson(json.graph);
23
        }
24
25
        if (check.assigned(json.graphs)) {
26
            // TODO: actually, multi graph should transform those properts to and from JSON too
27
            let graph = new JgfMultiGraph(null, null, null);
28
            _.each(json.graphs, (graphJson) => {
29
                graph.addGraph(this._graphFromJson(graphJson))
30
            });
31
            return graph;
32
        }
33
34
        throw new Error('Passed json has to to have a "graph" or "graphs" property.');
35
    }
36
37
    /**
38
     * Creates a single JGF graph from JSON.
39
     * @param {object} graphJson
40
     * @returns {JgfGraph}
41
     */
42
    static _graphFromJson(graphJson) {
43
        let graph = new JgfGraph(graphJson.type, graphJson.label, graphJson.directed, graphJson.metadata);
44
45
        _.each(graphJson.nodes, (node) => {
46
            graph.addNode(new JgfNode(node.id, node.label, node.metadata));
47
        });
48
49
        _.each(graphJson.edges, (edge) => {
50
            graph.addEdge(new JgfEdge(edge.source, edge.target, edge.relation, edge.label, edge.metadata, edge.directed));
51
        });
52
53
        return graph;
54
    }
55
56
    static _guardAgainstInvalidGraphObject(graph) {
57
        if (!check.instance(graph, JgfGraph) && !check.instance(graph, JgfMultiGraph)) {
58
            throw new Error('JgfJsonDecorator can only decorate graphs or multigraphs.');
59
        }
60
    }
61
62
    /**
63
     * Transforms either a graph or a multigraph object to a JSON representation as per the spec.
64
     * @param {JgfGraph,JgfMultiGraph} graph
65
     * @returns {object}
66
     */
67
    static toJson(graph) {
68
        this._guardAgainstInvalidGraphObject(graph);
69
70
        const isSingleGraph = check.instance(graph, JgfGraph);
71
72
        let normalizedGraph = this._normalizeToMultiGraph(graph);
73
        let allGraphsJson = {
74
            graphs: [],
75
        };
76
77
        _.each(normalizedGraph.graphs, (singleGraph) => {
78
79
            let singleGraphJson = {
80
                type: singleGraph.type,
81
                label: singleGraph.label,
82
                directed: singleGraph.directed,
83
                metadata: singleGraph.metadata,
84
                nodes: [],
85
                edges: [],
86
            };
87
88
            this._nodesToJson(singleGraph, singleGraphJson);
89
            this._edgesToJson(singleGraph, singleGraphJson);
90
91
            allGraphsJson.graphs.push(singleGraphJson);
92
        });
93
94
        if (isSingleGraph) {
95
            return this._removeNullValues({ graph: allGraphsJson.graphs[0] });
96
        }
97
98
        return this._removeNullValues(allGraphsJson);
99
    }
100
101
    static _removeNullValues(json) {
102
        return _.filterDeep(json, (value) => value !== null);
103
    }
104
105
    /**
106
     * @param {JgfGraph} graph
107
     * @param {object} json
108
     */
109
    static _edgesToJson(graph, json) {
110
        _.each(graph.edges, (edge) => {
111
            json.edges.push({
112
                source: edge.source,
113
                target: edge.target,
114
                relation: edge.relation,
115
                label: edge.label,
116
                metadata: edge.metadata,
117
                directed: edge.directed,
118
            });
119
        });
120
    }
121
122
    /**
123
     * @param {JgfGraph} graph
124
     * @param {object} json
125
     */
126
    static _nodesToJson(graph, json) {
127
        _.each(graph.nodes, (node) => {
128
            json.nodes.push({
129
                id: node.id,
130
                label: node.label,
131
                metadata: node.metadata,
132
            });
133
        });
134
    }
135
136
    static _normalizeToMultiGraph(graph) {
137
        let normalizedGraph = graph;
138
        if (check.instance(graph, JgfGraph)) {
139
            normalizedGraph = new JgfMultiGraph();
140
            normalizedGraph.addGraph(graph);
141
        }
142
143
        return normalizedGraph;
144
    }
145
}
146
147
module.exports = {
148
    JgfJsonDecorator,
149
};