/**
  * Collects all Shapes and any Connections attached to them, that are children or descendants of
  * the given Lane or Pool container. Only Shapes that are NOT Lanes are collected.
  *
  * @param containerShape the current Pool or Lane shape. This method is recursive and is initially
  *     invoked for the root container.
  * @param descendants the list of descendant Shapes and attached Connections
  * @param includeLanes if true, includes all Lane shapes in the results list
  */
 public static void collectChildren(
     ContainerShape containerShape, List<PictogramElement> descendants, boolean includeLanes) {
   for (PictogramElement pe : containerShape.getChildren()) {
     if (pe instanceof ContainerShape) {
       if (isLane(pe)) {
         if (includeLanes) descendants.add(pe);
         collectChildren((ContainerShape) pe, descendants, includeLanes);
       } else {
         if (isBpmnShape(pe)) {
           descendants.add(pe);
           for (Anchor a : ((ContainerShape) pe).getAnchors()) {
             for (Connection c : a.getIncomingConnections()) {
               if (c instanceof FreeFormConnection && !descendants.contains(c)) {
                 descendants.add(c);
               }
             }
             for (Connection c : a.getOutgoingConnections()) {
               if (c instanceof FreeFormConnection && !descendants.contains(c)) {
                 descendants.add(c);
               }
             }
           }
         }
       }
     }
   }
 }
  public static void setContainerChildrenVisible(
      IFeatureProvider fp, ContainerShape container, boolean visible) {
    List<PictogramElement> list = new ArrayList<PictogramElement>();
    list.addAll(container.getChildren());
    for (PictogramElement pe : list) {
      if (ShapeDecoratorUtil.isActivityBorder(pe)) continue;

      if (ShapeDecoratorUtil.isEventSubProcessDecorator(pe)) {
        pe.setVisible(!visible);
      } else pe.setVisible(visible);

      if (visible) FeatureSupport.updateLabel(fp, pe, null);
      if (pe instanceof AnchorContainer) {
        AnchorContainer ac = (AnchorContainer) pe;
        for (Anchor a : ac.getAnchors()) {
          for (Connection c : a.getOutgoingConnections()) {
            c.setVisible(visible);
            if (visible) FeatureSupport.updateLabel(fp, c, null);
            for (ConnectionDecorator decorator : c.getConnectionDecorators()) {
              decorator.setVisible(visible);
            }
          }
        }
      }
    }
  }
 protected boolean isMatch(Anchor target) {
   for (EObject sourceObject : source.getLink().getBusinessObjects()) {
     for (EObject targetObject : target.getLink().getBusinessObjects()) {
       if (isMatch(sourceObject, targetObject)) {
         return true;
       }
     }
   }
   return false;
 }
 private Set<Contract> getExistingConnections(AnchorContainer container) {
   Set<Contract> existingConnections = new LinkedHashSet<Contract>();
   for (Anchor anchor : container.getAnchors()) {
     for (Connection connection : anchor.getIncomingConnections()) {
       Object bo = getBusinessObjectForPictogramElement(connection.getStart());
       if (bo instanceof Contract || bo == null) {
         existingConnections.add((Contract) bo);
       }
     }
   }
   return existingConnections;
 }
 // Returns the TNodeTemplate belonging to the anchor, or null if not available
 private TNodeTemplate getTNodeTemplate(Anchor anchor) {
   if (anchor != null) {
     Object obj = getBusinessObjectForPictogramElement(anchor.getParent());
     if (obj instanceof TNodeTemplate) {
       return (TNodeTemplate) obj;
     }
   }
   return null;
 }
 private FlowNode getFlowNode(Anchor anchor) {
   if (anchor != null) {
     Object obj = getBusinessObjectForPictogramElement(anchor.getParent());
     if (obj instanceof FlowNode) {
       return (FlowNode) obj;
     }
   }
   return null;
 }
  public static void updateCategoryValues(IFeatureProvider fp, List<ContainerShape> shapes) {
    // Update CategoryValues for SequenceFlows also
    List<Connection> connections = new ArrayList<Connection>();
    for (ContainerShape cs : shapes) {
      updateCategoryValues(fp, cs);

      for (Anchor a : cs.getAnchors()) {
        for (Connection c : a.getIncomingConnections()) {
          if (!connections.contains(c)) connections.add(c);
        }
        for (Connection c : a.getOutgoingConnections()) {
          if (!connections.contains(c)) connections.add(c);
        }
      }
    }
    for (Connection c : connections) {
      updateCategoryValues(fp, c);
    }
  }
  public static void updateConnections(
      IFeatureProvider fp, AnchorContainer ac, List<Connection> alreadyUpdated) {
    for (int ai = 0; ai < ac.getAnchors().size(); ++ai) {
      Anchor a = ac.getAnchors().get(ai);
      for (int ci = 0; ci < a.getIncomingConnections().size(); ++ci) {
        Connection c = a.getIncomingConnections().get(ci);
        if (c instanceof FreeFormConnection) {
          if (!alreadyUpdated.contains(c)) {
            updateConnection(fp, c, true);
            alreadyUpdated.add(c);
          }
        }
      }
    }

    for (int ai = 0; ai < ac.getAnchors().size(); ++ai) {
      Anchor a = ac.getAnchors().get(ai);
      for (int ci = 0; ci < a.getOutgoingConnections().size(); ++ci) {
        Connection c = a.getOutgoingConnections().get(ci);
        if (c instanceof FreeFormConnection) {
          if (!alreadyUpdated.contains(c)) {
            updateConnection(fp, c, true);
            alreadyUpdated.add(c);
          }
        }
      }
    }
  }
  @Override
  public boolean update(IUpdateContext context) {
    _hasDoneChanges = false;

    // retrieve name from business model
    ContainerShape cs = (ContainerShape) context.getPictogramElement();
    Reference reference = (Reference) getBusinessObjectForPictogramElement(cs);

    // remove it if it's gone
    if (!GraphitiInternal.getEmfService().isObjectAlive(reference)) {
      IRemoveContext removeContext = new RemoveContext(context.getPictogramElement());
      final IRemoveFeature removeFeature = getFeatureProvider().getRemoveFeature(removeContext);
      if (removeFeature != null && removeFeature.canRemove(removeContext)) {
        removeFeature.remove(removeContext);
        _hasDoneChanges = removeFeature.hasDoneChanges();
        return true;
      }
    }

    // Set name in pictogram model
    String pictogramName = null;
    Text foundText = GraphitiUtil.findChildGA(cs.getGraphicsAlgorithm(), Text.class);
    if (foundText != null) {
      pictogramName = foundText.getValue();
    }
    String businessName = reference.getName();
    boolean updateNameNeeded =
        ((pictogramName == null && businessName != null)
            || (pictogramName != null && !pictogramName.contentEquals(businessName)));
    if (updateNameNeeded) {
      foundText.setValue(businessName);
      _hasDoneChanges = true;
    }

    // update the wires
    final Set<Contract> existingConnections = getExistingConnections(cs);
    final Anchor anchor = cs.getAnchors().get(0);
    for (ComponentReference promotedReference : reference.getPromote()) {
      if (promotedReference != null && !existingConnections.remove(promotedReference)) {
        for (PictogramElement pe :
            getFeatureProvider().getAllPictogramElementsForBusinessObject(promotedReference)) {
          if (pe instanceof Anchor) {
            AddConnectionContext addContext = new AddConnectionContext((Anchor) pe, anchor);
            addContext.setNewObject(reference);
            updatePictogramElement(getFeatureProvider().addIfPossible(addContext));
            _hasDoneChanges = true;
            break;
          }
        }
      }
    }

    for (Connection connection : new ArrayList<Connection>(anchor.getIncomingConnections())) {
      Object bo = getBusinessObjectForPictogramElement(connection.getStart());
      if (bo == null || existingConnections.remove(bo)) {
        RemoveContext removeContext = new RemoveContext(connection);
        IRemoveFeature removeFeature = getFeatureProvider().getRemoveFeature(removeContext);
        if (removeFeature.canExecute(removeContext)) {
          removeFeature.execute(removeContext);
          _hasDoneChanges = _hasDoneChanges || removeFeature.hasDoneChanges();
        }
      }
    }

    return _hasDoneChanges;
  }