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