/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * 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 * * http://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. */ package org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser; import java.util.LinkedList; import java.util.List; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser.common.ArrayParser; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser.common.IntegerFieldParser; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser.common.ObjectParser; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser.common.StringFieldParser; import org.kie.workbench.common.stunner.core.graph.Edge; import org.kie.workbench.common.stunner.core.graph.Node; import org.kie.workbench.common.stunner.core.graph.content.Bounds; import org.kie.workbench.common.stunner.core.graph.content.relationship.Dock; import org.kie.workbench.common.stunner.core.graph.content.view.BoundImpl; import org.kie.workbench.common.stunner.core.graph.content.view.View; import org.kie.workbench.common.stunner.core.graph.content.view.ViewConnector; public class NodeParser extends ElementParser<Node<View, Edge>> { private final List<Parser> children = new LinkedList<>(); public NodeParser(final String name, final Node<View, Edge> element) { super(name, element); } public NodeParser addChild(final Parser parser) { children.add(parser); return this; } @Override public void initialize(final Context context) { super.initialize(context); // Children. ArrayParser childrenParser = new ArrayParser("childShapes"); for (Parser childParser : children) { if (childParser instanceof ContextualParser) { ((ContextualParser) childParser).initialize(context); childrenParser.addParser(childParser); } } super.addParser(childrenParser); // Outgoing. ArrayParser outgoingParser = new ArrayParser("outgoing"); super.addParser(outgoingParser); List<Edge> outEdges = element.getOutEdges(); if (null != outEdges && !outEdges.isEmpty()) { for (Edge edge : outEdges) { String outId = null; if (isViewEdge(edge)) { // View connectors, such as sequence flows. outId = edge.getUUID(); } else if (isDockEdge(edge)) { // Docked nodes. Oryx marshallers do not expect an outgoing sequence flow id here, it expects the // id of the docked node. Node docked = edge.getTargetNode(); outId = docked.getUUID(); } if (null != outId) { outgoingParser.addParser(new ObjectParser("").addParser(new StringFieldParser("resourceId", outId))); } } } // Dockers - Only use if this node is docked. if (isDocked(element)) { Bounds.Bound ul = element.getContent().getBounds().getUpperLeft(); ObjectParser docker1ObjParser = new ObjectParser("") .addParser(new IntegerFieldParser("x", ul.getX().intValue())) .addParser(new IntegerFieldParser("y", ul.getY().intValue())); ArrayParser dockersParser = new ArrayParser("dockers") .addParser(docker1ObjParser); super.addParser(dockersParser); } } @Override protected void parseBounds(final Bounds.Bound ul, final Bounds.Bound lr) { Node<View, Edge> dockSource = getDockSourceNode(element); if (null == dockSource) { super.parseBounds(ul, lr); } else { Bounds.Bound parentUl = dockSource.getContent().getBounds().getUpperLeft(); Bounds.Bound parentLr = dockSource.getContent().getBounds().getLowerRight(); double bbW = lr.getX() - ul.getX(); double bbH = lr.getY() - ul.getY(); double ulx = parentUl.getX() + ul.getX() - (bbW / 2); double uly = parentUl.getY() + ul.getY() - (bbH / 2); double lrx = ulx + (bbW / 2); double lry = uly + (bbH / 2); Bounds.Bound newUl = new BoundImpl(ulx, uly); Bounds.Bound newLr = new BoundImpl(lrx, lry); super.parseBounds(newUl, newLr); } } private boolean isDocked(final Node<View, Edge> node) { return null != getDockSourceNode(node); } @SuppressWarnings("unchecked") private Node<View, Edge> getDockSourceNode(final Node<View, Edge> node) { List<Edge> inEdges = node.getInEdges(); if (null != inEdges && !inEdges.isEmpty()) { for (Edge edge : inEdges) { if (isDockEdge(edge)) { return edge.getSourceNode(); } } } return null; } private boolean isViewEdge(final Edge edge) { return edge.getContent() instanceof ViewConnector; } private boolean isDockEdge(final Edge edge) { return edge.getContent() instanceof Dock; } }