1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Processor = void 0;
|
4 | require("source-map-support/register");
|
5 | // TODO should I get rid of the lib above for production browser build?
|
6 | var lodash_1 = require("lodash");
|
7 | var fp_1 = require("lodash/fp");
|
8 | var hl = require("highland");
|
9 | var VError = require("verror");
|
10 | var iassign = require("immutable-assign");
|
11 | iassign.setOption({
|
12 | // Deep freeze both input and output. Used in development to make sure they don't change.
|
13 | // TODO watch issue and re-enable when addressed: https://github.com/engineforce/ImassignM/issues/11
|
14 | //freeze: true,
|
15 | ignoreIfNoChange: true
|
16 | });
|
17 | var gpml_utilities_1 = require("./gpml-utilities");
|
18 | var GraphIdManager_1 = require("./GraphIdManager");
|
19 | var GPML_ELEMENT_NAME_TO_KAAVIO_TYPE = {
|
20 | Anchor: "Burr",
|
21 | BiopaxRef: "Citation",
|
22 | DataNode: "SingleFreeNode",
|
23 | GraphicalLine: "Edge",
|
24 | Group: "Group",
|
25 | Interaction: "Edge",
|
26 | Label: "SingleFreeNode",
|
27 | //openControlledVocabulary: "Skip",
|
28 | //PublicationXref: "Skip",
|
29 | Shape: "SingleFreeNode",
|
30 | State: "Burr"
|
31 | };
|
32 | var VALUES_TO_SKIP = ["", null, undefined];
|
33 | // TODO update lodash/fp TS defs to use "x is ..."
|
34 | function isStringTS(x) {
|
35 | return fp_1.isString(x);
|
36 | }
|
37 | function isArrayTS(x) {
|
38 | return fp_1.isArray(x);
|
39 | }
|
40 | // NOTE: isPlainObject does not return true for an instance of a class
|
41 | function isRecord(x) {
|
42 | return !fp_1.isArray(x) && fp_1.isObject(x);
|
43 | }
|
44 | var Processor = /** @class */ (function () {
|
45 | function Processor(KeyMappings, KeyValueConverters, ValueMappings, ValueConverters) {
|
46 | var _this = this;
|
47 | this.output = {
|
48 | pathway: {
|
49 | // NOTE: GPML does not contain a way to express fill (background color).
|
50 | // It's always just white.
|
51 | fill: "white",
|
52 | strokeWidth: 0,
|
53 | stroke: "black",
|
54 | contains: [],
|
55 | drawAs: "rect",
|
56 | gpmlElementName: "Pathway",
|
57 | height: 0,
|
58 | // it appears type = {id: string} & type = {id?: string} makes id required.
|
59 | // TODO can we override that just for PathwayStarter?
|
60 | id: undefined,
|
61 | kaavioType: "Group",
|
62 | name: "New Pathway",
|
63 | // TODO what should the padding be?
|
64 | padding: 5,
|
65 | type: ["Pathway"],
|
66 | width: 0,
|
67 | x: 0,
|
68 | y: 0,
|
69 | zIndex: 0,
|
70 | // NOTE: these properties only apply contents of current element. They do not affect children.
|
71 | fontSize: 12,
|
72 | fontWeight: "bold",
|
73 | textAlign: "left",
|
74 | verticalAlign: "top"
|
75 | },
|
76 | entitiesById: {}
|
77 | };
|
78 | this.graphIdManager = new GraphIdManager_1.GraphIdManager();
|
79 | this.graphIdsByGraphRef = {};
|
80 | this.containedGraphIdsByGroupGraphId = {};
|
81 | this.containedGraphIdsByGroupGroupId = {};
|
82 | this.promisedGraphIdByGroupId = {};
|
83 | this.groupIdToGraphIdStream = hl();
|
84 | this.promisedGPMLElementByGraphId = {};
|
85 | this.gpmlElementStream = hl();
|
86 | this.promisedPvjsonEntityLatestByGraphId = {};
|
87 | this.pvjsonEntityLatestStream = hl();
|
88 | this.graphIdToZIndex = {};
|
89 | this.ensureGraphIdExists = function (gpmlElement) {
|
90 | var _a = _this, containedGraphIdsByGroupGroupId = _a.containedGraphIdsByGroupGroupId, graphIdManager = _a.graphIdManager, groupIdToGraphIdStream = _a.groupIdToGraphIdStream;
|
91 | var GroupId = gpmlElement.GroupId, GroupRef = gpmlElement.GroupRef;
|
92 | var GraphId = gpmlElement.GraphId;
|
93 | // TODO does this work for all elements? Are there any that we give an id that don't have one in GPML?
|
94 | // Does the schema allow the element to have a GraphId?
|
95 | if (!!GraphId) {
|
96 | // Does it actually have one?
|
97 | if (!gpml_utilities_1.isDefinedCXML(GraphId)) {
|
98 | // NOTE: we are making sure that elements that CAN have a GraphId
|
99 | // always DO have a GraphId. GraphIds are optional in GPML for Groups,
|
100 | // so we will add one if it's not already specified. But Pathway
|
101 | // elements never have GraphIds, so we don't add one for them.
|
102 | GraphId = gpmlElement.GraphId = graphIdManager.generateAndRecord();
|
103 | }
|
104 | else {
|
105 | graphIdManager.recordExisting(GraphId);
|
106 | }
|
107 | if (gpml_utilities_1.isDefinedCXML(GroupRef)) {
|
108 | containedGraphIdsByGroupGroupId[GroupRef] =
|
109 | containedGraphIdsByGroupGroupId[GroupRef] || [];
|
110 | containedGraphIdsByGroupGroupId[GroupRef].push(GraphId);
|
111 | }
|
112 | if (gpml_utilities_1.isDefinedCXML(GroupId)) {
|
113 | groupIdToGraphIdStream.write([GroupId, GraphId]);
|
114 | }
|
115 | }
|
116 | else {
|
117 | throw new Error("GraphId missing.");
|
118 | }
|
119 | return gpmlElement;
|
120 | };
|
121 | this.fillInGPMLPropertiesFromParent = fp_1.curry(function (gpmlParentElement, gpmlChildElement) {
|
122 | var Graphics = gpmlParentElement.Graphics;
|
123 | // NOTE: this makes some assumptions about the distribution of ZOrder values in GPML
|
124 | // TODO This is what we used to do. Do we still need to do this? Or can we just sort them
|
125 | // based on whether they are burrs of each other?
|
126 | //element.zIndex = element.hasOwnProperty('zIndex') ? element.zIndex : referencedElement.zIndex + 1 / elementCount;
|
127 | var propertiesToFillIn = {
|
128 | Graphics: {
|
129 | ZOrder: Graphics.ZOrder
|
130 | }
|
131 | };
|
132 | /* TODO can we delete this?
|
133 | if (isDefinedCXML(gpmlParentElement.GroupRef)) {
|
134 | propertiesToFillIn.GroupRef = gpmlParentElement.GroupRef;
|
135 | }
|
136 | //*/
|
137 | return lodash_1.defaultsDeep(gpmlChildElement, propertiesToFillIn);
|
138 | });
|
139 | this.getPvjsonEntityLatestByGraphId = function (graphId) {
|
140 | var promisedPvjsonEntity = _this.promisedPvjsonEntityLatestByGraphId[graphId];
|
141 | if (promisedPvjsonEntity) {
|
142 | return promisedPvjsonEntity;
|
143 | }
|
144 | else {
|
145 | var pvjsonEntityLatestStream_1 = _this.pvjsonEntityLatestStream;
|
146 | // NOTE: we don't need to set the cache here, because the cache is
|
147 | // set for every item that flows through pvjsonEntityLatestStream
|
148 | promisedPvjsonEntity = new Promise(function (resolve, reject) {
|
149 | pvjsonEntityLatestStream_1
|
150 | .observe()
|
151 | .find(function (pvjsonEntity) { return pvjsonEntity.id === graphId; })
|
152 | .errors(reject)
|
153 | .each(resolve);
|
154 | });
|
155 | return promisedPvjsonEntity;
|
156 | }
|
157 | };
|
158 | this.getGPMLElementByGraphId = function (GraphId) {
|
159 | var promisedGPMLElement = _this.promisedGPMLElementByGraphId[GraphId];
|
160 | if (promisedGPMLElement) {
|
161 | return promisedGPMLElement;
|
162 | }
|
163 | else {
|
164 | var gpmlElementStream_1 = _this.gpmlElementStream;
|
165 | // NOTE: we don't need to set the cache here, because the cache is
|
166 | // set for every item that flows through gpmlElementStream
|
167 | promisedGPMLElement = new Promise(function (resolve, reject) {
|
168 | gpmlElementStream_1
|
169 | .observe()
|
170 | .find(function (gpmlElement) { return gpmlElement.GraphId === GraphId; })
|
171 | .errors(reject)
|
172 | .each(resolve);
|
173 | });
|
174 | return promisedGPMLElement;
|
175 | }
|
176 | };
|
177 | this.preprocessGPMLElement = function (gpmlElement) {
|
178 | var _a = _this, ensureGraphIdExists = _a.ensureGraphIdExists, gpmlElementStream = _a.gpmlElementStream;
|
179 | var processedGPMLElement = ensureGraphIdExists(gpmlElement);
|
180 | // NOTE: side effect
|
181 | gpmlElementStream.write(processedGPMLElement);
|
182 | return processedGPMLElement;
|
183 | };
|
184 | this.processGPMLAndPropertiesAndType = fp_1.curry(function (gpmlElementName, gpmlElement) {
|
185 | var _a = _this, preprocessGPMLElement = _a.preprocessGPMLElement, processPropertiesAndType = _a.processPropertiesAndType, pvjsonEntityLatestStream = _a.pvjsonEntityLatestStream;
|
186 | return processPropertiesAndType(gpmlElementName, preprocessGPMLElement(gpmlElement));
|
187 | });
|
188 | this.processProperties = fp_1.curry(function (gpmlElement) {
|
189 | var processKV = _this.processKV;
|
190 | var entity = fp_1.fromPairs(fp_1.toPairsIn(gpmlElement).reduce(function (acc, x) { return fp_1.concat(acc, processKV(gpmlElement, x)); }, []));
|
191 | if (!!entity.rotation) {
|
192 | entity.textRotation = -1 * entity.rotation;
|
193 | }
|
194 | // TODO: why doesn't the following work?
|
195 | //return entity as PvjsonEntity & Comment;
|
196 | return entity;
|
197 | });
|
198 | this.processPropertiesAndType = fp_1.curry(function (gpmlElementName, gpmlElement) {
|
199 | var pvjsonEntity = _this.processType(gpmlElementName, _this.processProperties(gpmlElement));
|
200 | _this.pvjsonEntityLatestStream.write(pvjsonEntity);
|
201 | return pvjsonEntity;
|
202 | });
|
203 | this.processType = fp_1.curry(function (gpmlElementName, processed) {
|
204 | var kaavioType = GPML_ELEMENT_NAME_TO_KAAVIO_TYPE[gpmlElementName];
|
205 | processed.type = gpml_utilities_1.unionLSV(processed.type, gpmlElementName, kaavioType);
|
206 | if (processed.xrefDataSource && processed.xrefIdentifier) {
|
207 | processed.type = gpml_utilities_1.unionLSV(processed.type, processed.xrefDataSource + ":" + processed.xrefIdentifier);
|
208 | }
|
209 | if (!!kaavioType) {
|
210 | processed.kaavioType = kaavioType;
|
211 | }
|
212 | processed.gpmlElementName = gpmlElementName;
|
213 | return processed;
|
214 | });
|
215 | this.setPvjsonEntity = function (pvjsonEntity) {
|
216 | var _a = _this, graphIdToZIndex = _a.graphIdToZIndex, promisedPvjsonEntityLatestByGraphId = _a.promisedPvjsonEntityLatestByGraphId;
|
217 | var id = pvjsonEntity.id, zIndex = pvjsonEntity.zIndex;
|
218 | graphIdToZIndex[id] = zIndex;
|
219 | promisedPvjsonEntityLatestByGraphId[id] = Promise.resolve(pvjsonEntity);
|
220 | _this.output = iassign(_this.output, function (o) {
|
221 | return o.entitiesById;
|
222 | }, function (entitiesById) {
|
223 | entitiesById[pvjsonEntity.id] = pvjsonEntity;
|
224 | return entitiesById;
|
225 | });
|
226 | };
|
227 | this.getGPMLKeyAsJSFunctionName = function (gpmlKey) {
|
228 | // NOTE: gpmlKeyAsJSFunctionName is for attributes like "Data-Source", because
|
229 | // the following would be invalid JS:
|
230 | // export function Data-Source() {};
|
231 | // TODO what about things like spaces, etc.?
|
232 | return gpmlKey.replace("-", "");
|
233 | };
|
234 | this.getPvjsonValue = function (gpmlElement, gpmlKey, gpmlValue) {
|
235 | var _a = _this, getGPMLKeyAsJSFunctionName = _a.getGPMLKeyAsJSFunctionName, getPvjsonValue = _a.getPvjsonValue, processKV = _a.processKV, ValueConverters = _a.ValueConverters, ValueMappings = _a.ValueMappings;
|
236 | var gpmlKeyAsJSFunctionName = getGPMLKeyAsJSFunctionName(gpmlKey);
|
237 | var pvjsonValue;
|
238 | try {
|
239 | if (ValueConverters.hasOwnProperty(gpmlKeyAsJSFunctionName)) {
|
240 | return ValueConverters[gpmlKeyAsJSFunctionName](gpmlElement);
|
241 | }
|
242 | else if (isStringTS(gpmlValue)) {
|
243 | if (ValueMappings.hasOwnProperty(gpmlValue)) {
|
244 | return ValueMappings[gpmlValue];
|
245 | }
|
246 | else {
|
247 | return gpmlValue;
|
248 | }
|
249 | }
|
250 | else if (isArrayTS(gpmlValue)) {
|
251 | return gpmlValue.map(function (valueItem) {
|
252 | return getPvjsonValue(valueItem, gpmlKey, valueItem);
|
253 | });
|
254 | }
|
255 | else if (isRecord(gpmlValue)) {
|
256 | return fp_1.fromPairs(fp_1.toPairsIn(gpmlValue).reduce(function (acc, _a) {
|
257 | var key = _a[0], value = _a[1];
|
258 | processKV(gpmlValue, [key, value]).forEach(function (x) {
|
259 | acc.push(x);
|
260 | });
|
261 | return acc;
|
262 | }, []));
|
263 | }
|
264 | else {
|
265 | return gpmlValue;
|
266 | }
|
267 | }
|
268 | catch (err) {
|
269 | throw new VError(err, " when calling\n\t\t\t\tgetPvjsonValue(\n\t\t\t\t\t" + JSON.stringify(gpmlElement, null, "") + ",\n\t\t\t\t\t" + JSON.stringify(gpmlKey, null, "") + ",\n\t\t\t\t\t" + JSON.stringify(gpmlValue, null, "") + "\n\t\t\t\t)\n\t\t\t\t");
|
270 | }
|
271 | };
|
272 | this.processKV = fp_1.curry(function (gpmlElement, _a) {
|
273 | var gpmlKey = _a[0], gpmlValue = _a[1];
|
274 | try {
|
275 | var _b = _this, getGPMLKeyAsJSFunctionName = _b.getGPMLKeyAsJSFunctionName, getPvjsonValue = _b.getPvjsonValue, KeyMappings = _b.KeyMappings, KeyValueConverters = _b.KeyValueConverters, processKV_1 = _b.processKV, ValueMappings = _b.ValueMappings;
|
276 | var gpmlKeyAsJSFunctionName = getGPMLKeyAsJSFunctionName(gpmlKey);
|
277 | if (VALUES_TO_SKIP.indexOf(gpmlValue) > -1) {
|
278 | return [];
|
279 | }
|
280 | if (KeyValueConverters.hasOwnProperty(gpmlKeyAsJSFunctionName)) {
|
281 | return KeyValueConverters[gpmlKeyAsJSFunctionName](gpmlElement, KeyMappings, ValueMappings);
|
282 | }
|
283 | var pvjsonKey = KeyMappings[gpmlKey];
|
284 | // NOTE "pvjson:merge" is for elements like "Graphics", where they
|
285 | // are nested in GPML but are merged into the parent in pvjson.
|
286 | if (gpmlKey[0] === "_" ||
|
287 | pvjsonKey === "pvjson:delete" ||
|
288 | (fp_1.isObject(gpmlValue) && !gpml_utilities_1.isDefinedCXML(gpmlValue))) {
|
289 | // NOTE: we don't want to include "private" keys, such as
|
290 | // "_exists" or "_namespace".
|
291 | return [];
|
292 | }
|
293 | else if (pvjsonKey === "pvjson:merge") {
|
294 | return fp_1.toPairsIn(gpmlValue).reduce(function (acc, pair) { return fp_1.concat(acc, processKV_1(gpmlElement, pair)); }, []);
|
295 | }
|
296 | else if (pvjsonKey === "pvjson:each") {
|
297 | // NOTE: Example of what uses this is GPML Attribute.
|
298 | // (in GPML, 'Attribute' is an XML *ELEMENT* named "Attribute")
|
299 | return fp_1.toPairsIn(gpmlValue
|
300 | // NOTE: some attributes have empty values and will cause problems
|
301 | // if we don't use this filter to skip them.
|
302 | .filter(function (_a) {
|
303 | var Key = _a.Key, Value = _a.Value;
|
304 | return VALUES_TO_SKIP.indexOf(Value) === -1;
|
305 | })
|
306 | .map(function (_a) {
|
307 | var Key = _a.Key, Value = _a.Value;
|
308 | return processKV_1(gpmlElement, [Key, Value]);
|
309 | })
|
310 | .reduce(function (acc, _a) {
|
311 | var _b = _a[0], processedKey = _b[0], processedValue = _b[1];
|
312 | // NOTE: this looks more complicated than it needs to be,
|
313 | // but it's to handle the case where there are two or more
|
314 | // sibling Attribute elements that share the same Key.
|
315 | // I don't know of any cases of this in our actual GPML,
|
316 | // but the XSD does not require unique Keys for sibling
|
317 | // Attributes.
|
318 | if (acc.hasOwnProperty(processedKey)) {
|
319 | acc[processedKey] = gpml_utilities_1.unionLSV(acc[processedKey], processedValue);
|
320 | }
|
321 | else {
|
322 | acc[processedKey] = processedValue;
|
323 | }
|
324 | return acc;
|
325 | }, {}));
|
326 | }
|
327 | else {
|
328 | var pvjsonValue = getPvjsonValue(gpmlElement, gpmlKey, gpmlValue);
|
329 | // NOTE: we don't include key/value pairs when the value is missing
|
330 | if (VALUES_TO_SKIP.indexOf(pvjsonValue) === -1) {
|
331 | return [[pvjsonKey || fp_1.camelCase(gpmlKey), pvjsonValue]];
|
332 | }
|
333 | else {
|
334 | return [];
|
335 | }
|
336 | }
|
337 | }
|
338 | catch (err) {
|
339 | throw new VError(err, " when calling processor.processKV(\n\t\t\t\t\tgpmlElement: " + JSON.stringify(gpmlElement, null, " ") + ",\n\t\t\t\t\t[\n\t\t\t\t\t\tgpmlKey: " + gpmlKey + ",\n\t\t\t\t\t\tgpmlValue: " + JSON.stringify(gpmlValue, null, " ") + "\n\t\t\t\t\t]\n\t\t\t\t)\n\t\t\t\t");
|
340 | }
|
341 | });
|
342 | var _a = this, graphIdToZIndex = _a.graphIdToZIndex, graphIdsByGraphRef = _a.graphIdsByGraphRef, promisedGPMLElementByGraphId = _a.promisedGPMLElementByGraphId, gpmlElementStream = _a.gpmlElementStream, promisedGraphIdByGroupId = _a.promisedGraphIdByGroupId, groupIdToGraphIdStream = _a.groupIdToGraphIdStream, promisedPvjsonEntityLatestByGraphId = _a.promisedPvjsonEntityLatestByGraphId, pvjsonEntityLatestStream = _a.pvjsonEntityLatestStream;
|
343 | this.KeyMappings = KeyMappings;
|
344 | this.KeyValueConverters = KeyValueConverters;
|
345 | this.ValueMappings = ValueMappings;
|
346 | this.ValueConverters = ValueConverters;
|
347 | groupIdToGraphIdStream.each(function (_a) {
|
348 | var groupId = _a[0], graphId = _a[1];
|
349 | promisedGraphIdByGroupId[groupId] = Promise.resolve(graphId);
|
350 | });
|
351 | gpmlElementStream.each(function (gpmlElement) {
|
352 | promisedGPMLElementByGraphId[gpmlElement.GraphId] = Promise.resolve(gpmlElement);
|
353 | });
|
354 | pvjsonEntityLatestStream
|
355 | .doto(function (pvjsonEntity) {
|
356 | var id = pvjsonEntity.id, zIndex = pvjsonEntity.zIndex;
|
357 | graphIdToZIndex[id] = zIndex;
|
358 | promisedPvjsonEntityLatestByGraphId[id] = Promise.resolve(pvjsonEntity);
|
359 | })
|
360 | .errors(function (err, push) {
|
361 | push(new VError(err, " observed in pvjsonEntityLatestStream\n\t\t\t\t\t\t"));
|
362 | })
|
363 | .each(function (pvjsonEntity) { });
|
364 | /*
|
365 | TODO do we need this?
|
366 | endStream.each(function(x) {
|
367 | groupIdToGraphIdStream.end();
|
368 | gpmlElementStream.end();
|
369 | pvjsonEntityLatestStream.end();
|
370 | });
|
371 | //*/
|
372 | }
|
373 | return Processor;
|
374 | }());
|
375 | exports.Processor = Processor;
|
376 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJvY2Vzc29yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1Byb2Nlc3Nvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx1Q0FBcUM7QUFDckMsdUVBQXVFO0FBRXZFLGlDQUF1RDtBQUN2RCxnQ0FnQm1CO0FBQ25CLDZCQUErQjtBQUMvQiwrQkFBaUM7QUFDakMsMENBQTRDO0FBQzVDLE9BQU8sQ0FBQyxTQUFTLENBQUM7SUFDaEIseUZBQXlGO0lBQ3pGLG9HQUFvRztJQUNwRyxlQUFlO0lBQ2YsZ0JBQWdCLEVBQUUsSUFBSTtDQUN2QixDQUFDLENBQUM7QUFhSCxtREFBMkQ7QUFDM0QsbURBQWtEO0FBRWxELElBQU0sZ0NBQWdDLEdBQUc7SUFDdkMsTUFBTSxFQUFFLE1BQU07SUFDZCxTQUFTLEVBQUUsVUFBVTtJQUNyQixRQUFRLEVBQUUsZ0JBQWdCO0lBQzFCLGFBQWEsRUFBRSxNQUFNO0lBQ3JCLEtBQUssRUFBRSxPQUFPO0lBQ2QsV0FBVyxFQUFFLE1BQU07SUFDbkIsS0FBSyxFQUFFLGdCQUFnQjtJQUN2QixtQ0FBbUM7SUFDbkMsMEJBQTBCO0lBQzFCLEtBQUssRUFBRSxnQkFBZ0I7SUFDdkIsS0FBSyxFQUFFLE1BQU07Q0FDZCxDQUFDO0FBRUYsSUFBTSxjQUFjLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBYTdDLGtEQUFrRDtBQUNsRCxTQUFTLFVBQVUsQ0FBQyxDQUFNO0lBQ3hCLE9BQU8sYUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3JCLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxDQUFNO0lBQ3ZCLE9BQU8sWUFBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BCLENBQUM7QUFFRCxzRUFBc0U7QUFDdEUsU0FBUyxRQUFRLENBQUMsQ0FBTTtJQUN0QixPQUFPLENBQUMsWUFBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLGFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FB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 |
\ | No newline at end of file |