private void removeDuplicates(List<DiagramElementTreeNode> children) {
    List<DiagramElementTreeNode> duplicates = new ArrayList<DiagramElementTreeNode>();
    for (DiagramElementTreeNode node : children) {
      if (node.hasChildren()) removeDuplicates(node.getChildren());

      BaseElement be = node.getBaseElement();
      if (be instanceof Collaboration) {
        Collaboration c = (Collaboration) be;
        for (Participant p : c.getParticipants()) {
          for (DiagramElementTreeNode n : children) {
            if (n.getBaseElement() == p.getProcessRef()) {
              duplicates.add(n);
            }
          }
        }
      } else if (be instanceof ChoreographyActivity) {
        ChoreographyActivity c = (ChoreographyActivity) be;
        for (Participant p : c.getParticipantRefs()) {
          for (DiagramElementTreeNode n : children) {
            if (n.getBaseElement() == p) {
              duplicates.add(n);
            }
          }
        }
      }
    }
    if (!duplicates.isEmpty()) children.removeAll(duplicates);
  }
  @Override
  protected List<Object> getModelChildren() {
    List<Object> retList = new ArrayList<Object>();
    FlowElement elem = getFlowElement();

    if (elem instanceof FlowElementsContainer) {
      FlowElementsContainer container = (FlowElementsContainer) elem;
      return getFlowElementsContainerChildren(container);
    } else if (elem instanceof ChoreographyActivity) {
      ChoreographyActivity ca = (ChoreographyActivity) elem;
      retList.addAll(ca.getParticipantRefs());
    } else if (elem instanceof CallActivity) {
      // render a Call Activity with its called element target
      // (a Process or Global Task) as the child node.
      CallableElement target = ((CallActivity) elem).getCalledElementRef();
      if (target != null) {
        retList.add(target);
      }
    } else if (elem instanceof CatchEvent) {
      retList.addAll(((CatchEvent) elem).getEventDefinitions());
      retList.addAll(((CatchEvent) elem).getDataOutputAssociation());
    } else if (elem instanceof ThrowEvent) {
      retList.addAll(((ThrowEvent) elem).getEventDefinitions());
      retList.addAll(((ThrowEvent) elem).getDataInputAssociation());
    }

    if (elem instanceof Activity) {
      // Boundary Events are children nodes of Activities
      Definitions definitions = ModelUtil.getDefinitions(elem);
      if (definitions != null) {
        TreeIterator<EObject> iter = definitions.eAllContents();
        while (iter.hasNext()) {
          EObject o = iter.next();
          if (o instanceof BoundaryEvent && ((BoundaryEvent) o).getAttachedToRef() == elem) {
            retList.add(o);
          }
        }
        retList.addAll(((Activity) elem).getDataInputAssociations());
        retList.addAll(((Activity) elem).getDataOutputAssociations());
      }
    }
    return retList;
  }
  private BPMNShape createMissingDIElement(
      DiagramElementTreeNode node, int x, int y, List<BaseElement> created) {
    BaseElement element = node.getBaseElement();
    BPMNShape bpmnShape = null;
    BPMNDiagram bpmnDiagram = createDIDiagram(element);

    if (element instanceof Lane) {
      Lane lane = (Lane) element;
      bpmnShape = createDIShape(bpmnDiagram, lane, x, y);
      node.setBpmnShape(bpmnShape);

      y = createMissingDIElementChildren(node, x, y, created);
      created.add(lane);
    } else if (element instanceof FlowElementsContainer) {
      FlowElementsContainer container = (FlowElementsContainer) element;

      if (container instanceof SubProcess || container instanceof SubChoreography) {
        bpmnShape = createDIShape(bpmnDiagram, container, x, y);
        node.setBpmnShape(bpmnShape);
        created.add(container);
      }

      y = createMissingDIElementChildren(node, x, y, created);
    } else if (element instanceof Collaboration) {
      y = createMissingDIElementChildren(node, x, y, created);
    } else if (element instanceof Artifact) {
      bpmnShape = createDIShape(bpmnDiagram, element, x, y);
      node.setBpmnShape(bpmnShape);
      created.add(element);
    } else if (element instanceof Participant) {
      boolean doImport = true;
      if (node.getParent().getBaseElement() instanceof ChoreographyActivity) {
        // this is a Participant Band in a Choreography Activity
        doImport = false;
      }

      bpmnShape = createDIShape(bpmnDiagram, element, x, y, doImport);
      node.setBpmnShape(bpmnShape);
      created.add(element);
      if (!doImport) {
        ChoreographyActivity ca = (ChoreographyActivity) node.getParent().getBaseElement();
        bpmnShape.setChoreographyActivityShape(node.getParent().getBpmnShape());
        if (ca.getParticipantRefs().get(0) == element)
          bpmnShape.setParticipantBandKind(ParticipantBandKind.TOP_INITIATING);
        else bpmnShape.setParticipantBandKind(ParticipantBandKind.BOTTOM_NON_INITIATING);
      }
      createMissingDIElementChildren(node, x, y, created);
    } else if (element instanceof ConversationNode) {
      bpmnShape = createDIShape(bpmnDiagram, element, x, y);
      node.setBpmnShape(bpmnShape);
      created.add(element);
    } else if (element instanceof FlowNode) {
      boolean doImport = !(element instanceof ChoreographyActivity);
      bpmnShape = createDIShape(bpmnDiagram, element, x, y, doImport);
      node.setBpmnShape(bpmnShape);
      created.add(element);
      y = createMissingDIElementChildren(node, x, y, created);
      if (!doImport) importer.importShape(bpmnShape);
    } else if (isDataElement(element)) {
      bpmnShape = createDIShape(bpmnDiagram, element, x, y);
      node.setBpmnShape(bpmnShape);
      created.add(element);
    }
    return bpmnShape;
  }
  private void findMissingDIElements(DiagramElementTreeNode missing, BaseElement be) {
    if (be instanceof FlowElementsContainer) {
      // handles Process/SubProcess and Choreography/SubChoreography
      FlowElementsContainer container = (FlowElementsContainer) be;
      DiagramElementTreeNode parentNode = null;

      List<FlowElement> laneElements = new ArrayList<FlowElement>();
      for (LaneSet laneSet : container.getLaneSets()) {
        findMissingDIElements(missing, laneSet, laneElements);
      }

      for (FlowElement fe : container.getFlowElements()) {
        if (isMissingDIElement(fe) && !laneElements.contains(fe)) {
          if (fe instanceof SequenceFlow || fe instanceof DataObject || fe instanceof DataStore)
            continue;
          if (parentNode == null) parentNode = missing.addChild(container);
          parentNode.addChild(fe);
          if (fe instanceof FlowElementsContainer || fe instanceof ChoreographyActivity) {
            findMissingDIElements(parentNode, fe);
          }
        }
      }
      List<Artifact> artifacts = getArtifacts(container);
      if (artifacts != null) {
        for (Artifact a : artifacts) {
          if (isMissingDIElement(a) && !(a instanceof Association)) {
            if (parentNode == null) parentNode = missing.addChild(container);
            parentNode.addChild(a);
          }
        }
      }
    }

    // Choreography inherits both Collaboration and FlowElementsContainer
    if (be instanceof Collaboration) {
      // also handle Choreography
      Collaboration container = (Collaboration) be;
      DiagramElementTreeNode parentNode = null;
      for (Artifact a : container.getArtifacts()) {
        if (isMissingDIElement(a) && !(a instanceof Association)) {
          if (parentNode == null) parentNode = missing.addChild(container);
          parentNode.addChild(a);
        }
      }
      for (Participant p : container.getParticipants()) {
        boolean isParticipantBand = false;
        if (p.eContainer() instanceof Choreography) {
          // this may be a Choreography Activity Participant band
          Choreography choreography = (Choreography) p.eContainer();
          for (FlowElement fe : choreography.getFlowElements()) {
            if (fe instanceof ChoreographyActivity) {
              if (((ChoreographyActivity) fe).getParticipantRefs().contains(p)) {
                isParticipantBand = true;
                break;
              }
            }
          }
        }
        if (isMissingDIElement(p)
            && p.getProcessRef() != null
            && isMissingDIElement(p.getProcessRef())
            && !isParticipantBand) {
          if (parentNode == null) parentNode = missing.addChild(container);
          parentNode.addChild(p);
        }
      }
      for (ConversationNode c : container.getConversations()) {
        if (isMissingDIElement(c)) {
          if (parentNode == null) parentNode = missing.addChild(container);
          parentNode.addChild(c);
        }
      }
    } else if (be instanceof Participant) {
      Participant container = (Participant) be;
      if (container.getProcessRef() != null) {
        DiagramElementTreeNode parentNode = missing.addChild(container);
        parentNode.addChild(container.getProcessRef());
      }
    } else if (be instanceof ChoreographyActivity) {
      ChoreographyActivity container = (ChoreographyActivity) be;
      DiagramElementTreeNode parentNode = null;
      for (Participant p : container.getParticipantRefs()) {
        if (isMissingDIElement(p)) {
          if (parentNode == null) parentNode = missing.addChild(container);
          DiagramElementTreeNode child = parentNode.addChild(p);
          if (p.getProcessRef() != null) findMissingDIElements(child, p.getProcessRef());
        }
      }
    } else if (isDataElement(be)) {
      if (isMissingDIElement(be)) {
        missing.addChild(be);
      }
    }
  }