UNPKG

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