/**
   * transform binary association to n-ary association.
   *
   * @param createConnectionViewAndElementRequest the create connection view and element request
   * @param command the command
   * @return the command in charge of this job
   */
  private Command getAssociationToMultiAssociationCommand(
      CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest,
      Command command) {
    // 0. creation of variables
    command = new CompoundCommand();
    Point sourceLocation = null;
    Point targetLocation = null;
    Point nodeLocation = null;
    NamedElement newSemanticElement = null; // element that will be added as
    // client ou supplier of the
    // association
    EStructuralFeature feature = null; // role client or supplier
    EditPart sourceEditPart = createConnectionViewAndElementRequest.getSourceEditPart();
    EditPart targetEditPart = createConnectionViewAndElementRequest.getTargetEditPart();
    View associationView = null;
    Association association = null;
    View parentView = null;

    Property sourceEnd = null;
    Property targetEnd = null;

    // ---------------------------------------------------------
    // help to debug
    //		System.err.println("\n+ 0. creation of variables");
    //		System.err.println("+-> editting domain"+ getEditingDomain());
    //		System.err.println("+-> sourceEditpart:" + sourceEditPart);
    //		System.err.println("+-> targetEditPart:" + targetEditPart);
    // ---------------------------------------------------------

    // 1. initialization
    ICommandProxy startcommand =
        ((ICommandProxy) createConnectionViewAndElementRequest.getStartCommand());
    if (startcommand == null) {
      return null;
    }
    Iterator<?> ite = ((CompositeCommand) startcommand.getICommand()).iterator();

    while (ite.hasNext()) {
      ICommand currentCommand = (ICommand) ite.next();
      if (currentCommand instanceof SetConnectionBendpointsCommand) {
        sourceLocation = ((SetConnectionBendpointsCommand) currentCommand).getSourceRefPoint();
        targetLocation = ((SetConnectionBendpointsCommand) currentCommand).getTargetRefPoint();
      }
    }

    if (targetEditPart != null) {
      // the source or the target must be a association
      // look for the edit part that represent the editpart
      if (((View) sourceEditPart.getModel()).getElement() != null
          && ((View) sourceEditPart.getModel()).getElement() instanceof Association) {
        associationView = ((View) sourceEditPart.getModel());
        association = (Association) ((View) sourceEditPart.getModel()).getElement();
        nodeLocation = sourceLocation;
        newSemanticElement = (NamedElement) ((View) targetEditPart.getModel()).getElement();
        feature = UMLPackage.eINSTANCE.getTypedElement_Type();
        sourceEnd =
            AssociationEndSourceLabelHelper.getInstance()
                .getUMLElement(
                    (org.eclipse.gef.GraphicalEditPart) sourceEditPart.getChildren().get(0));
        targetEnd =
            AssociationEndTargetLabelHelper.getInstance()
                .getUMLElement(
                    (org.eclipse.gef.GraphicalEditPart) sourceEditPart.getChildren().get(1));
      }

      if (((View) targetEditPart.getModel()).getElement() != null
          && ((View) targetEditPart.getModel()).getElement() instanceof Association) {
        associationView = ((View) targetEditPart.getModel());
        association = (Association) ((View) targetEditPart.getModel()).getElement();
        nodeLocation = targetLocation;
        newSemanticElement = (NamedElement) ((View) sourceEditPart.getModel()).getElement();
        feature = UMLPackage.eINSTANCE.getTypedElement_Type();
        sourceEnd =
            AssociationEndSourceLabelHelper.getInstance()
                .getUMLElement(
                    (org.eclipse.gef.GraphicalEditPart) targetEditPart.getChildren().get(0));
        targetEnd =
            AssociationEndTargetLabelHelper.getInstance()
                .getUMLElement(
                    (org.eclipse.gef.GraphicalEditPart) targetEditPart.getChildren().get(1));
      }

      if (associationView == null || (targetEditPart.getModel() instanceof Edge)) {
        return null;
      }
      parentView = (View) associationView.eContainer();
      // ---------------------------------------------------------
      // help to debug
      //			System.err.println("+ 1. initialization");
      //			System.err.println("+-> sourceLocation:" + sourceLocation);
      //			System.err.println("+-> targetLocation:" + targetLocation);
      //			System.err.println("+-> AssociationView:" + associationView);
      //			System.err.println("+-> association:" + association);
      //			System.err.println("+-> nodeLocation:" + nodeLocation);
      //			System.err.println("+-> newSemanticElement:" + newSemanticElement);
      //			System.err.println("+-> feature:" + feature);
      //			System.err.println("+-> parentView:" + parentView);
      // ---------------------------------------------------------
      // 8 Ensure that all member ends belong to the association
      ArrayList<Property> ownedProperty = new ArrayList<Property>();
      ownedProperty.addAll(association.getMemberEnds());
      IElementEditService provider = ElementEditServiceUtils.getCommandProvider(association);
      if (provider != null) {
        SetRequest setRequest =
            new SetRequest(
                association, UMLPackage.eINSTANCE.getAssociation_OwnedEnd(), ownedProperty);
        ICommand iCommand = provider.getEditCommand(setRequest);
        ((CompoundCommand) command).add(new ICommandProxy(iCommand));
      }

      // 2. Remove the view of the association
      DeleteCommand deleteCommand =
          new DeleteLinkDuringCreationCommand(
              getEditingDomain(), (Edge) associationView, sourceEditPart.getViewer());
      deleteCommand.setReuseParentTransaction(true);
      Command removecommand = new ICommandProxy(deleteCommand);
      // to execute
      ((CompoundCommand) command).add(removecommand);

      // ((CompoundCommand)command).add(removecommand);

      // ---------------------------------------------------------
      // help to debug
      //			System.err.println("+ 2. Remove the view of the association");
      //			System.err.println("+-> command:" + command.canExecute());
      // ---------------------------------------------------------

      // 3. set a new end association in the UML model
      // 3.1 creation of the property
      CreateElementRequest request =
          new CreateElementRequest(
              getEditingDomain(),
              association,
              UMLElementTypes.Property_3005,
              UMLPackage.eINSTANCE.getAssociation_OwnedEnd());
      request.setParameter("type", newSemanticElement);
      EditElementCommand propertyCreateCommand = new PropertyCommandForAssociation(request);
      propertyCreateCommand.setReuseParentTransaction(true);
      ((CompoundCommand) command).add(new ICommandProxy(propertyCreateCommand));

      // 3. Node creation at this position
      View associationViewSource = ((Edge) associationView).getSource();
      View associationViewTarget = ((Edge) associationView).getTarget();
      AssociationDiamonViewCreateCommand nodeCreation =
          new AssociationDiamonViewCreateCommand(
              getEditingDomain(),
              parentView,
              sourceEditPart.getViewer(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
              nodeLocation,
              new SemanticAdapter(association, null));
      nodeCreation.setReuseParentTransaction(true);
      ((CompoundCommand) command).add(new ICommandProxy(nodeCreation));

      // 4. reconstruction of the old link by taking in account the old
      // connection
      ConnectionViewDescriptor viewDescriptor =
          new ConnectionViewDescriptor(
              UMLElementTypes.Association_4019,
              ((IHintedType) UMLElementTypes.Association_4019).getSemanticHint(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint());

      // 5. reconstruction of the first branch between old source to node
      ICommand firstBranchCommand =
          new GraphicalAssociationBranchViewCommand(
              getEditingDomain(),
              (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
              new SemanticAdapter(null, associationViewSource),
              sourceEditPart.getViewer(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
              viewDescriptor,
              sourceEnd);

      // ICommand firstBranchCommand = new
      // CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
      // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(),
      // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null,
      // associationViewSource), sourceEditPart.getViewer(),
      // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
      ((GraphicalAssociationBranchViewCommand) firstBranchCommand).setElement(association);
      ((CompoundCommand) command).add(new ICommandProxy(firstBranchCommand));
      // 6. reconstruction of the second branch between node to old target
      ICommand secondBranchCommand =
          new GraphicalAssociationBranchViewCommand(
              getEditingDomain(),
              (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
              new SemanticAdapter(null, associationViewTarget),
              sourceEditPart.getViewer(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
              viewDescriptor,
              targetEnd);

      // ICommand secondBranchCommand = new
      // CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
      // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(),
      // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null,
      // associationViewTarget), sourceEditPart.getViewer(),
      // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
      ((GraphicalAssociationBranchViewCommand) secondBranchCommand).setElement(association);
      ((CompoundCommand) command).add(new ICommandProxy(secondBranchCommand));

      // 7. Create of the third branch between node and target our source.
      ICommand thirdBranchCommand = null;

      if (associationView.equals((sourceEditPart.getModel()))) {
        // third branch node and target
        thirdBranchCommand =
            new GraphicalAssociationBranchViewCommand(
                getEditingDomain(),
                (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
                new SemanticAdapter(null, targetEditPart.getModel()),
                sourceEditPart.getViewer(),
                ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
                viewDescriptor,
                request);

        // thirdBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
        // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(),
        // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null,
        // targetEditPart.getModel()), sourceEditPart.getViewer(),
        // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
      } else {
        // third branch source and node
        thirdBranchCommand =
            new GraphicalAssociationBranchViewCommand(
                getEditingDomain(),
                new SemanticAdapter(null, sourceEditPart.getModel()),
                (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
                sourceEditPart.getViewer(),
                ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
                viewDescriptor,
                request);

        // thirdBranchCommand = new CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
        // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(), new
        // SemanticAdapter(null, sourceEditPart.getModel()),
        // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), sourceEditPart.getViewer(),
        // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);
      }
      ((GraphicalAssociationBranchViewCommand) thirdBranchCommand).setElement(association);
      ((CompoundCommand) command).add(new ICommandProxy(thirdBranchCommand));
    }
    return command;
  }
  /**
   * code to create new branch.
   *
   * @param createConnectionViewAndElementRequest the create connection view and element request
   * @param command that will contain sub commands
   * @return the command in charge of the branch creation
   */
  private Command getBranchAssociationCommand(
      CreateConnectionViewAndElementRequest createConnectionViewAndElementRequest,
      Command command) {
    command = new CompoundCommand();
    // init
    EditPart sourceEditPart = createConnectionViewAndElementRequest.getSourceEditPart();
    EditPart targetEditPart = createConnectionViewAndElementRequest.getTargetEditPart();

    if ((targetEditPart.getModel() instanceof Edge)) {
      return null;
    }
    if (targetEditPart != null) {
      // the source or the target must be a association
      // look for the edit part that represent the editpart
      EObject association = null;
      NamedElement newSemanticElement = null;
      if (((View) sourceEditPart.getModel()).getElement() != null
          && ((View) sourceEditPart.getModel()).getElement() instanceof Association) {
        association = ((View) sourceEditPart.getModel()).getElement();
        newSemanticElement = (NamedElement) ((View) targetEditPart.getModel()).getElement();
      }

      if (((View) targetEditPart.getModel()).getElement() != null
          && ((View) targetEditPart.getModel()).getElement() instanceof Association) {
        association = ((View) targetEditPart.getModel()).getElement();
        newSemanticElement = (NamedElement) ((View) sourceEditPart.getModel()).getElement();
      }
      // System.err.println("step init, can execute?" + command.canExecute());
      // 0. add semantic
      CreateElementRequest request =
          new CreateElementRequest(
              getEditingDomain(),
              association,
              UMLElementTypes.Property_3005,
              UMLPackage.eINSTANCE.getAssociation_OwnedEnd());
      request.setParameter("type", newSemanticElement);
      EditElementCommand propertyCreateCommand = new PropertyCommandForAssociation(request);
      ((CompoundCommand) command).add(new ICommandProxy(propertyCreateCommand));

      // System.err.println("0. add semantic, can execute?" + command.canExecute());
      // 1. add the branch graphically
      ConnectionViewDescriptor viewDescriptor =
          new ConnectionViewDescriptor(
              UMLElementTypes.Association_4019,
              ((IHintedType) UMLElementTypes.Association_4019).getSemanticHint(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint());
      GraphicalAssociationBranchViewCommand aBranchCommand =
          new GraphicalAssociationBranchViewCommand(
              getEditingDomain(),
              new SemanticAdapter(null, sourceEditPart.getModel()),
              new SemanticAdapter(null, targetEditPart.getModel()),
              sourceEditPart.getViewer(),
              ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
              viewDescriptor,
              request);
      // CustomDeferredCreateConnectionViewCommand aBranchCommand = new
      // CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
      // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(), new
      // SemanticAdapter(null, sourceEditPart.getModel()), new SemanticAdapter(null,
      // targetEditPart.getModel()), sourceEditPart.getViewer(),
      // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewDescriptor, null);

      aBranchCommand.setElement(association);
      ((CompoundCommand) command).add(new ICommandProxy(aBranchCommand));
      // System.err.println("1. add the branch graphically, can execute?" + command.canExecute());
      return command;
    }
    return UnexecutableCommand.INSTANCE;
  }
  public Command dropMutliAssociation(
      Association association,
      EditPartViewer viewer,
      PreferencesHint diagramPreferencesHint,
      Point location,
      View containerView) {
    Command command = new CompoundCommand();
    // 0. Obtain list of property to display
    ArrayList<Property> endToDisplay = new ArrayList(association.getMemberEnds());

    // 1. creatiuon of the diamon of association
    AssociationDiamonViewCreateCommand nodeCreation =
        new AssociationDiamonViewCreateCommand(
            getEditingDomain(),
            containerView,
            viewer,
            diagramPreferencesHint,
            location,
            new SemanticAdapter(association, null));
    ((CompoundCommand) command).add(new ICommandProxy(nodeCreation));

    // 2. for each element create a graphical representation of the type and
    // finally the branch
    Iterator<Property> iteratorProp = endToDisplay.iterator();
    int index = 0;
    while (iteratorProp.hasNext()) {
      index += 1;
      // source editPart
      EditPart sourceEditPart = null;
      // end of the association end
      Property currentEnd = iteratorProp.next();

      // look for if an editpart exist for this element
      Collection<EditPart> editPartSet = viewer.getEditPartRegistry().values();
      Iterator<EditPart> editPartIterator = editPartSet.iterator();

      while (editPartIterator.hasNext() && sourceEditPart == null) {

        EditPart currentEditPart = editPartIterator.next();

        if ((!(currentEditPart instanceof CompartmentEditPart))
            && currentEditPart instanceof GraphicalEditPart
            && currentEnd
                .getType()
                .equals(((GraphicalEditPart) currentEditPart).resolveSemanticElement())) {
          sourceEditPart = currentEditPart;
        }
      }
      // descriptor for the branch
      ConnectionViewDescriptor viewBranchDescriptor =
          new ConnectionViewDescriptor(
              UMLElementTypes.Association_4019,
              ((IHintedType) UMLElementTypes.Association_4019).getSemanticHint(),
              diagramPreferencesHint);

      // the editpart exist -> only creation of the branch
      if (sourceEditPart != null) {

        GraphicalAssociationBranchViewCommand aBranchCommand =
            new GraphicalAssociationBranchViewCommand(
                getEditingDomain(),
                (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
                new SemanticAdapter(null, sourceEditPart.getModel()),
                sourceEditPart.getViewer(),
                ((IGraphicalEditPart) sourceEditPart).getDiagramPreferencesHint(),
                viewBranchDescriptor,
                currentEnd);

        // CustomDeferredCreateConnectionViewCommand aBranchCommand = new
        // CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
        // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(),
        // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(), new SemanticAdapter(null,
        // sourceEditPart.getModel()), sourceEditPart.getViewer(),
        // ((IGraphicalEditPart)sourceEditPart).getDiagramPreferencesHint(), viewBranchDescriptor,
        // null);

        aBranchCommand.setElement(association);
        ((CompoundCommand) command).add(new ICommandProxy(aBranchCommand));
      } else { // the editpart does not exist

        // creation of the node
        IAdaptable elementAdapter = new EObjectAdapter(currentEnd.getType());
        ViewDescriptor descriptor =
            new ViewDescriptor(
                elementAdapter, Node.class, null, ViewUtil.APPEND, false, diagramPreferencesHint);

        // get the command and execute it.
        CreateCommand nodeCreationCommand =
            new CreateCommand(getEditingDomain(), descriptor, containerView);
        ((CompoundCommand) command).add(new ICommandProxy(nodeCreationCommand));
        SetBoundsCommand setBoundsCommand =
            new SetBoundsCommand(
                getEditingDomain(),
                "move",
                (IAdaptable) nodeCreationCommand.getCommandResult().getReturnValue(),
                new Point(location.x + 200, location.y + index * 100));
        ((CompoundCommand) command).add(new ICommandProxy(setBoundsCommand));
        // Creation of the branch
        GraphicalAssociationBranchViewCommand aBranchCommand =
            new GraphicalAssociationBranchViewCommand(
                getEditingDomain(),
                (IAdaptable) nodeCreation.getCommandResult().getReturnValue(),
                (IAdaptable) nodeCreationCommand.getCommandResult().getReturnValue(),
                viewer,
                diagramPreferencesHint,
                viewBranchDescriptor,
                currentEnd);

        // CustomDeferredCreateConnectionViewCommand aBranchCommand = new
        // CustomDeferredCreateConnectionViewCommand(getEditingDomain(),
        // ((IHintedType)UMLElementTypes.Association_4019).getSemanticHint(),
        // (IAdaptable)nodeCreation.getCommandResult().getReturnValue(),
        // (IAdaptable)nodeCreationCommand.getCommandResult().getReturnValue(), viewer,
        // diagramPreferencesHint, viewBranchDescriptor, null);

        aBranchCommand.setElement(association);
        ((CompoundCommand) command).add(new ICommandProxy(aBranchCommand));
        // creation of the link
      }
    }
    return command;
  }