/* * Copyright 2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Flo } from 'spring-flo'; import { dia } from 'jointjs'; /** * Convert a text representation to a graph. * * @author Alex Boyko * @author Andy Clement */ class TextToGraphConverter { constructor(private flo : Flo.EditorContext, private metamodel : Map>) { } matchGroup(name : string, incoming : number, outgoing : number) : string { let score = Number.MIN_VALUE; let group : string; Array.from(this.metamodel.keys()).filter(group => this.metamodel.get(group).has(name)).map(group => this.metamodel.get(group).get(name)).find(match => { let failedConstraintsNumber = 0; if (match.group === 'source') { if (incoming > 0) { failedConstraintsNumber++; } if (outgoing > 1) { failedConstraintsNumber++; } } else if (match.group === 'sink') { if (incoming > 1) { failedConstraintsNumber++; } if (outgoing > 0) { failedConstraintsNumber++; } } else if (match.group === 'processor') { if (incoming > 1) { failedConstraintsNumber++; } if (outgoing > 1) { failedConstraintsNumber++; } } if (failedConstraintsNumber < score) { score = failedConstraintsNumber; group = match.group; } return failedConstraintsNumber === 0; }); return group; } convertToGraph(input : string) { this.flo.getGraph().clear(); // input is a string like this (3 nodes: foo, goo and hoo): foo --a=b --c=d > goo --d=e --f=g>hoo let trimmed = input.trim(); if (trimmed.length===0) { return; } trimmed.split('\n').forEach(line => { let lastNode : dia.Element; line.trim().split('>').map(e => e.trim()).forEach(element => { let startOfProps = element.indexOf(' '); let name = element.trim(); let properties = new Map(); if (startOfProps !== -1) { name = element.substring(0,startOfProps); element.substring(startOfProps+1).trim().split(' ').map(pv => pv.trim()).filter(pv => pv.length).forEach(pv => { var equalsIndex = pv.indexOf('='); // The 2 skips the '--' let key = pv.substring(2,equalsIndex); let value = pv.substring(equalsIndex+1); properties.set(key, value); }); } let group = this.matchGroup(name, 0, 0); let newNode = this.flo.createNode(Flo.getMetadata(this.metamodel,name,group),properties,{x:0,y:0}); newNode.attr('.label/text',name); if (lastNode) { let sourceView = this.flo.getPaper().findViewByModel(lastNode); let sourceMagnet = Flo.findMagnetByClass(sourceView, '.output-port'); let sourceEnd : Flo.LinkEnd = { id: lastNode.id, selector: sourceView.getSelector(sourceMagnet, undefined), }; if (sourceMagnet.getAttribute('port')) { sourceEnd.port = sourceMagnet.getAttribute('port'); } let targetView = this.flo.getPaper().findViewByModel(newNode); let targetMagnet = Flo.findMagnetByClass(targetView, '.input-port'); let targetEnd : Flo.LinkEnd = { id: newNode.id, selector: targetView.getSelector(targetMagnet, undefined), }; if (targetMagnet.getAttribute('port')) { targetEnd.port = targetMagnet.getAttribute('port'); } this.flo.createLink(sourceEnd, targetEnd); } lastNode = newNode; }) }); } } export function convertTextToGraph(flo : Flo.EditorContext, metamodel : Map>, input : string) { return new TextToGraphConverter(flo, metamodel).convertToGraph(input); }