protected void internalLayout(Shape shape) {
    DiagramElement diagramElement =
        BusinessObjectUtil.getFirstElementOfType(shape, DiagramElement.class);

    if (diagramElement instanceof BPMNShape || diagramElement instanceof BPMNEdge) {
      Layouter.layoutShapeAfterResize(shape, getFeatureProvider());
    }
  }
 protected List<Shape> getFlowElementChildren(ContainerShape containerShape) {
   List<Shape> children = new ArrayList<Shape>();
   for (Shape s : containerShape.getChildren()) {
     FlowElement bo = BusinessObjectUtil.getFirstElementOfType(s, FlowElement.class);
     if (s instanceof ContainerShape && bo != null) {
       children.add(s);
     }
   }
   return children;
 }
  @Override
  public boolean canUpdate(IUpdateContext context) {
    PictogramElement pictogramElement = context.getPictogramElement();

    // TODO: Label property not correctly set
    if (LabelUtil.isLabel(pictogramElement)
        || BusinessObjectUtil.getFirstElementOfType(pictogramElement, BPMNShape.class) == null) {
      return false;
    }

    Object businessObject = getBusinessObjectForPictogramElement(pictogramElement);

    return businessObject != null;
  }
  protected Connection createNewConnection(
      ModelHandler mh, ContainerShape oldShape, ContainerShape newShape) {

    Anchor sourceAnchor = LayoutUtil.getCenterAnchor(oldShape);
    Anchor targetAnchor = LayoutUtil.getCenterAnchor(newShape);

    // TODO: Use create features to create connection
    CreateConnectionContext createConnectionContext = new CreateConnectionContext();
    createConnectionContext.setSourcePictogramElement(oldShape);
    createConnectionContext.setTargetPictogramElement(newShape);
    createConnectionContext.setSourceAnchor(sourceAnchor);
    createConnectionContext.setTargetAnchor(targetAnchor);

    FlowNode oldObject = BusinessObjectUtil.getFirstElementOfType(oldShape, FlowNode.class);
    FlowNode newObject = BusinessObjectUtil.getFirstElementOfType(newShape, FlowNode.class);

    AddConnectionContext acc = new AddConnectionContext(sourceAnchor, targetAnchor);
    SequenceFlow flow = mh.createSequenceFlow(oldObject, newObject);
    acc.setNewObject(flow);

    Connection connection = (Connection) getFeatureProvider().addIfPossible(acc);

    return connection;
  }
  protected ContainerShape createNewShape(
      ModelHandler mh, ContainerShape oldShape, EClass newType) {
    ILayoutService layoutService = Graphiti.getLayoutService();
    boolean horz = Bpmn2Preferences.getInstance().isHorizontalDefault();

    ILocation loc = layoutService.getLocationRelativeToDiagram(oldShape);
    int x = loc.getX();
    int y = loc.getY();
    int xOffset = 0;
    int yOffset = 0;
    GraphicsAlgorithm ga = oldShape.getGraphicsAlgorithm();
    int width = ga.getWidth();
    int height = ga.getHeight();

    BPMN2FeatureProvider fp = (BPMN2FeatureProvider) getFeatureProvider();
    AbstractCreateFeature createFeature =
        (AbstractCreateFeature) fp.getCreateFeatureForBusinessObject(newType.getInstanceClass());

    CreateContext createContext = new CreateContext();
    createContext.putProperty(AbstractCreateFlowElementFeature.SKIP_ADD_GRAPHICS, true);
    createContext.setTargetContainer(oldShape.getContainer());

    FlowElement newObject = null;
    if (createFeature != null) {
      newObject = (FlowElement) createFeature.create(createContext)[0];
    } else {
      newObject = (FlowElement) mh.create(newType);
    }

    ContainerShape containerShape = oldShape.getContainer();
    if (containerShape != getDiagram()) {
      // we are adding a new shape to a control (e.g a SubProcess)
      // so we need to adjust the location to be relative to the
      // control instead of the diagram
      loc = layoutService.getLocationRelativeToDiagram(containerShape);
      xOffset = loc.getX();
      yOffset = loc.getY();
    }
    BaseElement oldObject = BusinessObjectUtil.getFirstElementOfType(oldShape, BaseElement.class);

    if (oldObject instanceof Lane) {
      ((Lane) oldObject).getFlowNodeRefs().add((FlowNode) newObject);
    }
    AddContext ac = new AddContext(new AreaContext(), newObject);
    AbstractAddBpmnShapeFeature af =
        (AbstractAddBpmnShapeFeature) getFeatureProvider().getAddFeature(ac);
    int w = af.getDefaultWidth();
    int h = af.getDefaultHeight();
    if (horz) {
      x += width + 50 + w / 2;
      y += height / 2;
      boolean done = false;
      while (!done) {
        done = true;
        List<Shape> shapes = getFlowElementChildren(containerShape);
        for (Shape s : shapes) {
          if (GraphicsUtil.intersects(s, x - w / 2, y - h / 2, w, h)) {
            y += 100;
            done = false;
            break;
          }
        }
      }
    } else {
      x += width / 2;
      y += height + 50 + h / 2;
      boolean done = false;
      while (!done) {
        done = true;
        List<Shape> shapes = getFlowElementChildren(containerShape);
        for (Shape s : shapes) {
          if (GraphicsUtil.intersects(s, x - w / 2, y - h / 2, w, h)) {
            x += 100;
            done = false;
            break;
          }
        }
      }
    }
    ac.setX(x - xOffset);
    ac.setY(y - yOffset);
    ac.setTargetContainer(oldShape.getContainer());

    return (ContainerShape) getFeatureProvider().addIfPossible(ac);
  }