Package org.eclipse.bpmn2.modeler.core.di

Source Code of org.eclipse.bpmn2.modeler.core.di.DIImport

/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
*  All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.eclipse.bpmn2.modeler.core.di;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.bpmn2.Association;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.ConversationLink;
import org.eclipse.bpmn2.DataAssociation;
import org.eclipse.bpmn2.Event;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.InteractionNode;
import org.eclipse.bpmn2.ItemAwareElement;
import org.eclipse.bpmn2.Lane;
import org.eclipse.bpmn2.MessageFlow;
import org.eclipse.bpmn2.Participant;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.SubChoreography;
import org.eclipse.bpmn2.SubProcess;
import org.eclipse.bpmn2.di.BPMNDiagram;
import org.eclipse.bpmn2.di.BPMNEdge;
import org.eclipse.bpmn2.di.BPMNPlane;
import org.eclipse.bpmn2.di.BPMNShape;
import org.eclipse.bpmn2.di.BpmnDiFactory;
import org.eclipse.bpmn2.modeler.core.Activator;
import org.eclipse.bpmn2.modeler.core.ModelHandler;
import org.eclipse.bpmn2.modeler.core.features.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.bpmn2.modeler.core.utils.Tuple;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.bpmn2.modeler.core.validation.LiveValidationContentAdapter;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dc.Point;
import org.eclipse.dd.di.DiagramElement;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.AreaContext;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.FixPointAnchor;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.mm.pictograms.impl.FreeFormConnectionImpl;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
import org.eclipse.graphiti.services.IPeService;

@SuppressWarnings("restriction")
public class DIImport {

  public static final String IMPORT_PROPERTY = DIImport.class.getSimpleName().concat(".import");

  private Diagram diagram;
  private TransactionalEditingDomain domain;
  private ModelHandler modelHandler;
  private IFeatureProvider featureProvider;
  private HashMap<BaseElement, PictogramElement> elements;
  private final IPeService peService = Graphiti.getPeService();
  private final IGaService gaService = Graphiti.getGaService();

  private final LiveValidationContentAdapter liveValidationContentAdapter = new LiveValidationContentAdapter();
  /**
   * Look for model diagram interchange information and generate all shapes for the diagrams.
   *
   * NB! Currently only first found diagram is generated.
   */
  public void generateFromDI() {
    final List<BPMNDiagram> diagrams = modelHandler.getAll(BPMNDiagram.class);
   
    elements = new HashMap<BaseElement, PictogramElement>();
    domain.getCommandStack().execute(new RecordingCommand(domain) {
      @Override
      protected void doExecute() {

        if (diagrams.size() == 0) {
          BPMNPlane plane = BpmnDiFactory.eINSTANCE.createBPMNPlane();
          plane.setBpmnElement(modelHandler.getOrCreateProcess(modelHandler.getInternalParticipant()));

          BPMNDiagram d = BpmnDiFactory.eINSTANCE.createBPMNDiagram();
          d.setPlane(plane);

          modelHandler.getDefinitions().getDiagrams().add(d);
          featureProvider.link(diagram, d);
        }

        // First: add all IDs to our ID mapping table
        for (BPMNDiagram d : diagrams) {
          TreeIterator<EObject> iter = d.eAllContents();
          while (iter.hasNext()) {
            ModelUtil.addID( iter.next() );
          }
        }
       
        for (BPMNDiagram d : diagrams) {
          featureProvider.link(diagram, d);
          BPMNPlane plane = d.getPlane();
          if (plane.getBpmnElement() == null) {
            plane.setBpmnElement(modelHandler.getOrCreateProcess(modelHandler.getInternalParticipant()));
          }
          List<DiagramElement> ownedElement = plane.getPlaneElement();

          // FIXME: here we should create a new diagram and an editor page
          importShapes(ownedElement);
          importConnections(ownedElement);

          relayoutLanes(ownedElement);
          // FIXME: we don't really want to leave, but we also don't want all diagrams mixed together
          return;
        }
      }

    });
  }

  public void setDiagram(Diagram diagram) {
    this.diagram = diagram;
  }

  public void setDomain(TransactionalEditingDomain editingDomain) {
    this.domain = editingDomain;

  }

  public void setModelHandler(ModelHandler modelHandler) {
    this.modelHandler = modelHandler;
  }

  public void setFeatureProvider(IFeatureProvider featureProvider) {
    this.featureProvider = featureProvider;
  }

  private void importShapes(List<DiagramElement> ownedElement) {
    for (DiagramElement diagramElement : ownedElement) {
      if (diagramElement instanceof BPMNShape) {
        createShape((BPMNShape) diagramElement);
      }
    }
  }

  private void importConnections(List<DiagramElement> ownedElement) {
    for (DiagramElement diagramElement : ownedElement) {
      if (diagramElement instanceof BPMNEdge) {
        createEdge((BPMNEdge) diagramElement);
      }
    }
  }

  private void relayoutLanes(List<DiagramElement> ownedElement) {
    for (DiagramElement diagramElement : ownedElement) {
      if (diagramElement instanceof BPMNShape && ((BPMNShape) diagramElement).getBpmnElement() instanceof Lane) {
        BaseElement lane = ((BPMNShape) diagramElement).getBpmnElement();
        ContainerShape shape = (ContainerShape) BusinessObjectUtil.getFirstBaseElementFromDiagram(diagram, lane);
        FeatureSupport.redraw(shape);
      }
    }
  }

  /**
   * Find a Graphiti feature for given shape and generate necessary diagram elements.
   *
   * @param shape
   */
  private void createShape(BPMNShape shape) {
    BaseElement bpmnElement = shape.getBpmnElement();
    if (shape.getChoreographyActivityShape() != null) {
      // FIXME: we currently generate participant bands automatically
      return;
    }
    IAddFeature addFeature = featureProvider.getAddFeature(new AddContext(new AreaContext(), bpmnElement));

    if (addFeature == null) {
      Activator.logStatus(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Element not supported: "
          + bpmnElement.eClass().getName()));
      return;
    }

    AddContext context = new AddContext();
    context.putProperty(IMPORT_PROPERTY, true);
    context.setNewObject(bpmnElement);
    context.setSize((int) shape.getBounds().getWidth(), (int) shape.getBounds().getHeight());

    if (bpmnElement instanceof Lane) {
      handleLane(bpmnElement, context, shape);
    } else if (bpmnElement instanceof FlowNode) {
      handleFlowNode((FlowNode) bpmnElement, context, shape);
    } else {
      context.setTargetContainer(diagram);
      context.setLocation((int) shape.getBounds().getX(), (int) shape.getBounds().getY());
    }

    if (addFeature.canAdd(context)) {
      PictogramElement newContainer = addFeature.add(context);
      featureProvider.link(newContainer, new Object[] { bpmnElement, shape });
      if (bpmnElement instanceof Participant) {
        elements.put(((Participant) bpmnElement).getProcessRef(), newContainer);
      }
      elements.put(bpmnElement, newContainer);
      handleEvents(bpmnElement, newContainer);
    }
   
    ModelUtil.addID(bpmnElement);
    String id = bpmnElement.getId();
    if (shape.getId() == null)
      shape.setId(id);
   
    if (!bpmnElement.eAdapters().contains(liveValidationContentAdapter)) {
      bpmnElement.eAdapters().add(liveValidationContentAdapter);
    }
  }

  private void handleEvents(BaseElement bpmnElement, PictogramElement newContainer) {
    if (bpmnElement instanceof Event) {
      EList<EObject> contents = bpmnElement.eContents();
      for (EObject obj : contents) {

        AddContext context = new AddContext();
        context.setTargetContainer((ContainerShape) newContainer);
        context.setNewObject(obj);

        IAddFeature aFeat = featureProvider.getAddFeature(context);
        if (aFeat != null && aFeat.canAdd(context)) {
          aFeat.add(context);
        }
      }
    }
  }

  private void handleLane(BaseElement bpmnElement, AddContext context, BPMNShape shape) {
    BaseElement parent = (BaseElement) ((Lane) bpmnElement).eContainer().eContainer();
    ContainerShape cont = diagram;

    // find the process this lane belongs to
    for (BaseElement be : elements.keySet()) {
      if (be instanceof Participant) {
        Process processRef = ((Participant) be).getProcessRef();
        if (processRef != null && parent.getId().equals(processRef.getId())) {
          cont = (ContainerShape) elements.get(be);
          break;
        }
      } else if (be instanceof Process) {
        if (be.getId().equals(parent.getId())) {
          cont = (ContainerShape) elements.get(be);
          break;
        }
      } else if (be instanceof Lane) {
        if (be.getId().equals(parent.getId())) {
          cont = (ContainerShape) elements.get(be);
          break;
        }
      }
    }

    context.setTargetContainer(cont);
    context.setLocation((int) shape.getBounds().getX(), (int) shape.getBounds().getY());

  }

  private void handleFlowNode(FlowNode node, AddContext context, BPMNShape shape) {
    ContainerShape target = diagram;
    int x = (int) shape.getBounds().getX();
    int y = (int) shape.getBounds().getY();

    // find a correct container element
    List<Lane> lanes = node.getLanes();
    if ((node.eContainer() instanceof SubProcess || (node.eContainer() instanceof Process || node.eContainer() instanceof SubChoreography)
        && lanes.isEmpty())) {
      ContainerShape containerShape = (ContainerShape) elements.get(node.eContainer());
      if (containerShape != null) {
        target = containerShape;
        ILocation loc = Graphiti.getPeLayoutService().getLocationRelativeToDiagram(target);
        x -= loc.getX();
        y -= loc.getY();
      }
    } else if (!lanes.isEmpty()) {
      for (Lane lane : lanes) {
        target = (ContainerShape) elements.get(lane);
        ILocation loc = Graphiti.getPeLayoutService().getLocationRelativeToDiagram(target);
        x -= loc.getX();
        y -= loc.getY();
      }
    }
    context.setTargetContainer(target);
    context.setLocation(x, y);
  }

  private BaseElement findElementById ( String id ) {
    if (elements.keySet().size() > 0) {
      Iterator<BaseElement> keys = elements.keySet().iterator();
      while (keys.hasNext()) {
        BaseElement key = keys.next();
        if (key != null && key.getId().equals(id))
          return key;
      }
    }
    return null;
  }
 
  private Tuple<BaseElement, BaseElement> getSourceAndTargetByID String id ) {
    BaseElement source = null;
    BaseElement target = null;
    int indexOfDash = id.indexOf('-');
    if (indexOfDash > -1) {
      String srcRefFromId = id.substring(0, indexOfDash);
      String tgtRefFromId = id.substring(indexOfDash + 1, id.length());
      source = findElementById(srcRefFromId);
      target = findElementById(tgtRefFromId);
    }
    return new Tuple<BaseElement, BaseElement>(source, target);
  }
 
  /**
   * Find a Graphiti feature for given edge and generate necessary connections and bendpoints.
   *
   * @param shape
   */
  private void createEdge(BPMNEdge bpmnEdge) {
    BaseElement bpmnElement = bpmnEdge.getBpmnElement();
    EObject source = null;
    EObject target = null;
    PictogramElement se = null;
    PictogramElement te = null;

    String id = bpmnElement.getId();

    // for some reason connectors don't have a common interface
    if (bpmnElement instanceof MessageFlow) {
      source = ((MessageFlow) bpmnElement).getSourceRef();
      target = ((MessageFlow) bpmnElement).getTargetRef();
     
      // for jbpm-3241, if we're importing from jbpm5, we won't have
      // the sourceref & targetref set initially - have to get it from
      // the id
      if (source == null && target == null) {
        Tuple<BaseElement, BaseElement> sourceAndTargetFromID =
            getSourceAndTargetByID(id);
        if (sourceAndTargetFromID.getFirst() != null) {
          source = sourceAndTargetFromID.getFirst();
          ((MessageFlow) bpmnElement).setSourceRef((InteractionNode) source);
        }
        if (sourceAndTargetFromID.getSecond() != null) {
          target = sourceAndTargetFromID.getSecond();
          ((MessageFlow) bpmnElement).setTargetRef((InteractionNode) target);
        }
      }
      se = elements.get(source);
      te = elements.get(target);
    } else if (bpmnElement instanceof SequenceFlow) {
      source = ((SequenceFlow) bpmnElement).getSourceRef();
      target = ((SequenceFlow) bpmnElement).getTargetRef();
     
      // for jbpm-3241, if we're importing from jbpm5, we won't have
      // the sourceref & targetref set initially - have to get it from
      // the id
      if (source == null && target == null) {
        Tuple<BaseElement, BaseElement> sourceAndTargetFromID =
            getSourceAndTargetByID(id);
        if (sourceAndTargetFromID.getFirst() != null) {
          source = sourceAndTargetFromID.getFirst();
          ((SequenceFlow) bpmnElement).setSourceRef((FlowNode) source);
        }
        if (sourceAndTargetFromID.getSecond() != null) {
          target = sourceAndTargetFromID.getSecond();
          ((SequenceFlow) bpmnElement).setTargetRef((FlowNode) target);
        }
      }
      se = elements.get(source);
      te = elements.get(target);
    } else if (bpmnElement instanceof Association) {
      source = ((Association) bpmnElement).getSourceRef();
      target = ((Association) bpmnElement).getTargetRef();

      // for jbpm-3241, if we're importing from jbpm5, we won't have
      // the sourceref & targetref set initially - have to get it from
      // the id
      if (source == null && target == null) {
        Tuple<BaseElement, BaseElement> sourceAndTargetFromID =
            getSourceAndTargetByID(id);
        if (sourceAndTargetFromID.getFirst() != null) {
          source = sourceAndTargetFromID.getFirst();
          ((Association) bpmnElement).setSourceRef((FlowNode) source);
        }
        if (sourceAndTargetFromID.getSecond() != null) {
          target = sourceAndTargetFromID.getSecond();
          ((Association) bpmnElement).setTargetRef((FlowNode) target);
        }
      }
      se = elements.get(source);
      te = elements.get(target);
    } else if (bpmnElement instanceof ConversationLink) {
      source = ((ConversationLink) bpmnElement).getSourceRef();
      target = ((ConversationLink) bpmnElement).getTargetRef();

      // for jbpm-3241, if we're importing from jbpm5, we won't have
      // the sourceref & targetref set initially - have to get it from
      // the id
      if (source == null && target == null) {
        Tuple<BaseElement, BaseElement> sourceAndTargetFromID =
            getSourceAndTargetByID(id);
        if (sourceAndTargetFromID.getFirst() != null) {
          source = sourceAndTargetFromID.getFirst();
          ((ConversationLink) bpmnElement).setSourceRef((InteractionNode) source);
        }
        if (sourceAndTargetFromID.getSecond() != null) {
          target = sourceAndTargetFromID.getSecond();
          ((ConversationLink) bpmnElement).setTargetRef((InteractionNode) target);
        }
      }
      se = elements.get(source);
      te = elements.get(target);
    } else if (bpmnElement instanceof DataAssociation) {
      // Data Association allows connections for multiple starting points, we don't support it yet
      List<ItemAwareElement> sourceRef = ((DataAssociation) bpmnElement).getSourceRef();
      ItemAwareElement targetRef = ((DataAssociation) bpmnElement).getTargetRef();
      if (sourceRef != null) {
        source = sourceRef.get(0);
      }
      target = targetRef;
      do {
        se = elements.get(source);
        source = source.eContainer();
      } while (se == null && source.eContainer() != null);
      do {
        te = elements.get(target);
        target = target.eContainer();
      } while (te == null && target.eContainer() != null);
    }

    ModelUtil.addID(bpmnElement);
   
    if (source != null && target != null) {
      addSourceAndTargetToEdge(bpmnEdge, source, target);
    }

    if (se != null && te != null) {

      createConnectionAndSetBendpoints(bpmnEdge, se, te);
     
    } else {
      Activator.logStatus(new Status(IStatus.WARNING, Activator.PLUGIN_ID,
          "Couldn't find target element, probably not supported! Source: " + source + " Target: " + target
              + " Element: " + bpmnElement));
    }
  }

  private void addSourceAndTargetToEdge(BPMNEdge bpmnEdge, EObject source, EObject target) {
    // We get most of the information from the BpmnEdge, not from the referencing business object. Because of this
    // we must ensure, that the edge contains necessary information.
    if (bpmnEdge.getSourceElement() == null) {
      bpmnEdge.setSourceElement(modelHandler.findDIElement(diagram, (BaseElement) source));
    }
    if (bpmnEdge.getTargetElement() == null) {
      bpmnEdge.setTargetElement(modelHandler.findDIElement(diagram, (BaseElement) target));
    }
  }

  private Connection createConnectionAndSetBendpoints(BPMNEdge bpmnEdge, PictogramElement sourceElement,
      PictogramElement targetElement) {
    FixPointAnchor sourceAnchor = createAnchor(sourceElement);
    FixPointAnchor targetAnchor = createAnchor(targetElement);

    AddConnectionContext context = new AddConnectionContext(sourceAnchor, targetAnchor);
    context.setNewObject(bpmnEdge.getBpmnElement());

    IAddFeature addFeature = featureProvider.getAddFeature(context);
    if (addFeature != null && addFeature.canAdd(context)) {
      context.putProperty(IMPORT_PROPERTY, true);
      Connection connection = (Connection) addFeature.add(context);

      if (connection instanceof FreeFormConnectionImpl) {
        FreeFormConnectionImpl freeForm = (FreeFormConnectionImpl) connection;

        List<Point> waypoint = bpmnEdge.getWaypoint();
        int size = waypoint.size() - 1;

        setAnchorLocation(sourceElement, sourceAnchor, waypoint.get(0));
        setAnchorLocation(targetElement, targetAnchor, waypoint.get(size));

        for (int i = 1; i < size; i++) {
          DIUtils.addBendPoint(freeForm, waypoint.get(i));
        }
      }
      featureProvider.link(connection, new Object[] { bpmnEdge.getBpmnElement(), bpmnEdge });
      return connection;
    } else {
      Activator.logStatus(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Unsupported feature "
          + ((EObject) context.getNewObject()).eClass().getName()));
    }
    return null;
  }

  private FixPointAnchor createAnchor(PictogramElement elem) {
    FixPointAnchor sa = peService.createFixPointAnchor((AnchorContainer) elem);
    sa.setReferencedGraphicsAlgorithm(elem.getGraphicsAlgorithm());
    Rectangle rect = gaService.createInvisibleRectangle(sa);
    gaService.setSize(rect, 1, 1);
    return sa;
  }

  private void setAnchorLocation(PictogramElement elem, FixPointAnchor anchor, Point point) {
    org.eclipse.graphiti.mm.algorithms.styles.Point p = gaService.createPoint((int) point.getX(),
        (int) point.getY());

    ILocation loc = Graphiti.getPeLayoutService().getLocationRelativeToDiagram((Shape) elem);

    int x = p.getX() - loc.getX();
    int y = p.getY() - loc.getY();

    p.setX(x);
    p.setY(y);

    anchor.setLocation(p);
  }
}
TOP

Related Classes of org.eclipse.bpmn2.modeler.core.di.DIImport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.