org.eclipse.papyrus.uml.diagram.activity.activitygroup.GroupRequestAdvisor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.papyrus.uml.diagram.activity.activitygroup.GroupRequestAdvisor.java

Source

/*****************************************************************************
 * Copyright (c) 2011 Atos.
 *
 *    
 * All rights reserved. This program and the accompanying materials
 * are 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:
 *   Arthur Daussy (Atos) - Initial API and implementation
 *   Arthur Daussy - 371712 : 372745: [ActivityDiagram] Major refactoring group framework
 *
 *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.activity.activitygroup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.naming.InitialContext;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.emf.type.core.commands.MoveElementsCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.core.log.LogHelper;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.ICompositeCreator;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.INotification;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.NotificationRunnable;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.Type;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.IContext;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.editpolicy.notifiers.GroupNotifyingOnMoveEditPolicy;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.editpolicy.notifiers.IGroupNotifier;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.predicates.AncestorFilter;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.predicates.DescendantsFilter;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.predicates.DescendantsFilterIGroupNotifier;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.predicates.SameContainerFilter;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.request.IGroupRequest;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.request.SetDeferredRequest;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.ui.IntegrateViewToConfigureComposite;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.utils.DebugUtils;
import org.eclipse.papyrus.uml.diagram.activity.activitygroup.utils.Utils;
import org.eclipse.papyrus.uml.diagram.activity.commands.DeferredSetValueCommand;
import org.eclipse.papyrus.uml.diagram.activity.commands.RunNotificationCommand;
import org.eclipse.papyrus.uml.diagram.activity.edit.part.ActivityGroup.IGroupCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.activity.part.UMLDiagramEditorPlugin;
import org.eclipse.papyrus.uml.diagram.common.commands.RemoveValueCommand;
import org.eclipse.papyrus.uml.diagram.common.commands.RemoveValueRequest;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.uml2.uml.ActivityGroup;
import org.eclipse.uml2.uml.Element;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

public class GroupRequestAdvisor implements IGroupRequestAdvisor {

    /**
     * Exception message
     */
    private static final String UNABLE_TO_GET_THE_INTIAL_TARGET_REQUEST_BOUNDS = "Unable to get the intial target request bounds";////$NON-NLS-1$

    /**
     * Debug message
     */
    private static final String CHILDREN_REFERENCES_ARE = " ---- Children references are : ---- ";

    /**
     * Debug message
     */
    private static final String ALL_PARENT_REFERENCES_ARE = " ---- All parent references are : ---- ";

    /**
     * Runnable to run command to change parent of selected element
     * 
     * @author arthur daussy
     * 
     */
    private final class ChangeGraphicalParentRunnable implements NotificationRunnable {

        /**
         * New graphical host
         */
        private final IGraphicalEditPart host;

        /**
         * Initial request
         */
        private final IGroupRequest request;

        /**
         * List of all modified view
         * Used to compute list of modfied files
         */
        private List<View> viewTomodify;

        /**
         * Constructor
         * 
         * @param host
         *        New graphical host
         * @param request
         *        Initial request
         */
        private ChangeGraphicalParentRunnable(IGraphicalEditPart host, IGroupRequest request) {
            this.host = host;
            this.request = request;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.papyrus.ui.toolbox.notification.NotificationRunnable#run(org.eclipse.papyrus.ui.toolbox.notification.builders.IContext)
         */
        public void run(IContext context) {
            IntegrateViewToConfigureComposite composite = (IntegrateViewToConfigureComposite) context
                    .get(IContext.COMPOSITE_CREATED);
            final INotification notif = (INotification) context.get(IContext.NOTIFICATION_OBJECT);
            CompositeTransactionalCommand ccMovingElement = new CompositeTransactionalCommand(
                    request.getHostRequest().getEditingDomain(), "Move graphical elements into a new host");////$NON-NLS-1$
            /*
             * Use to calculate impacted file
             */
            viewTomodify = Lists.newArrayList();
            IGraphicalEditPart hostEditPart = request.getHostRequest();
            viewTomodify.add(host.getNotationView());
            for (IGroupNotifier notifier : composite.getSelectedNotifier()) {
                IGraphicalEditPart notifierEditPart = notifier.getHostEditPart();
                IGraphicalEditPart hostCompartmentEditPart = request.getNodeDescpitor()
                        .getCompartmentPartFromView(hostEditPart);
                /*
                 * debugging label
                 */
                if (DebugUtils.isDebugging()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("Move ");
                    stringBuilder.append(Utils.getCorrectLabel(notifierEditPart));
                    stringBuilder.append(" to ");
                    stringBuilder.append(Utils.getCorrectLabel(hostEditPart));
                    DebugUtils.getLog().info(stringBuilder.toString());
                }
                if (notifierEditPart != null) {
                    EObject semanticElementToDrop = notifierEditPart.resolveSemanticElement();
                    if (semanticElementToDrop != null && hostCompartmentEditPart != null) {
                        /*
                         * Request to change graphical parent
                         */
                        ChangeBoundsRequest chdBoundsRequest = new ChangeBoundsRequest(RequestConstants.REQ_ADD);
                        chdBoundsRequest.setEditParts(notifierEditPart);
                        viewTomodify.add(notifierEditPart.getNotationView());
                        Command dropcommand = hostCompartmentEditPart.getCommand(chdBoundsRequest);
                        if (dropcommand != null) {
                            ccMovingElement.compose(new CommandProxy(dropcommand));
                        }
                    } else {
                        //log error
                    }
                } else {
                    //log error
                }
            }
            /*
             * Execute resulting command
             */
            if (ccMovingElement != null && !ccMovingElement.isEmpty()) {
                host.getEditingDomain().getCommandStack().execute(new GMFtoEMFCommandWrapper(ccMovingElement));
            }
            notif.delete();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.papyrus.ui.toolbox.notification.NotificationRunnable#getLabel()
         */
        public String getLabel() {
            return "OK";
        }

        /**
         * @return the list of all EObject modifed
         */
        public List getModifiedObject() {
            return viewTomodify == null ? Collections.emptyList() : viewTomodify;
        }
    }

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance()
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder {

        public static final GroupRequestAdvisor instance = new GroupRequestAdvisor();
    }

    /**
     * Get the instance of {@link GroupRequestAdvisor}
     * 
     * @return
     */
    public static GroupRequestAdvisor getInstance() {
        return SingletonHolder.instance;
    }

    /**
     * Store all the listener
     */
    private Multimap<EObject, IGroupNotifier> listenners;

    /**
     * Logger
     */
    private static LogHelper log = new LogHelper(UMLDiagramEditorPlugin.getInstance());

    /***
     * Private constructor
     */
    private GroupRequestAdvisor() {
        listenners = ArrayListMultimap.create();
    }

    /**
     * Add a {@link IGroupNotifier}
     * 
     * @param editpolicy
     */
    public void addListenner(EObject eObject, IGroupNotifier editpolicy) {
        getListenerRegistry().put(eObject, editpolicy);
    }

    /**
     * Remove a {@link IGroupNotifier}
     * 
     * @param editpolicy
     */
    public void removeListenner(IGroupNotifier editpolicy) {
        if (editpolicy == null) {
            return;
        }
        Iterator<Entry<EObject, IGroupNotifier>> iterator = getListenerRegistry().entries().iterator();
        while (iterator.hasNext()) {
            Entry<EObject, IGroupNotifier> entry = iterator.next();
            if (editpolicy.equals(entry.getValue())) {
                iterator.remove();
            }
        }
    }

    public ICommand notifyGroupFramework(IGroupRequest request) {
        if (DebugUtils.isDebugging()) {
            log.debug("***********************BEGIN : Group Request Advisor***********************************");
        }
        /******************
         * Handling parent
         ******************/
        CompositeCommand cc = new CompositeCommand("Global command from GroupRequestAdvisor");
        Request initialRequest = request.getInitialRequest();
        if (initialRequest instanceof ChangeBoundsRequest) {
            handleMove(request, cc);
        } else if (initialRequest instanceof GroupRequest
                && RequestConstants.REQ_DELETE.equals(initialRequest.getType())) {
            handleDelete(request, cc);
        }
        if (cc != null && !cc.isEmpty()) {
            return cc;
        }
        return null;
    }

    protected void handleDelete(IGroupRequest request, CompositeCommand cc) {
        //      request.getNodeDescpitor().getChildrenReferences()
    }

    /**
     * Handle move
     * 
     * @param request
     * @param cc
     */
    protected void handleMove(IGroupRequest request, CompositeCommand cc) {
        /*
         * All parent
         */
        fillRequestWithAllPossibleParent(request);
        fillRequestWithAllPossibleChildren(request);
        Object elementAdapter = request.getTargetElement().getAdapter(EObject.class);
        if (elementAdapter instanceof EObject) {
            /*
             * Handle children
             */
            handleSemanticChildren(request, cc, (EObject) elementAdapter);
            /*
             * Semantic of all the parent
             */
            handleSemanticParents(request, cc, (EObject) elementAdapter);
        }
        if (DebugUtils.isDebugging()) {
            log.debug("***********************END : Group Request Advisor***********************************");
        }
        //      /*
        //       * For all new child send request
        //       * For all GrChild create new request from old one and use dispatcher
        //       */
        //      if(cc != null && !cc.isEmpty()) {
        //         return cc;
        //      }
        //      return null;
    }

    /**
     * Handle all the children of the group (graphical and non graphical children)
     * 
     * @param request
     * @param cc
     * @param targetElement
     */
    protected void handleSemanticChildren(final IGroupRequest request, CompositeCommand cc, EObject targetElement) {
        List<EObject> graphicalChildren = Lists.newArrayList();
        /*
         * There is graphical childrne only when the node is moving
         */
        if (request.getInitialRequest() instanceof ChangeBoundsRequest) {
            graphicalChildren = handleGraphicalChildren(request, cc);
        }
        /*
         * Unset
         */
        for (Entry<EReference, EObject> oldChildrenEntry : Utils.getOldChildren(request).entries()) {
            Multimap<EReference, EObject> allActualChildren = request.getChildrenEReferenceMap();
            EReference ref = oldChildrenEntry.getKey();
            if (ref != null) {
                if (!allActualChildren.containsEntry(oldChildrenEntry.getValue(), ref)) {
                    EReference eOpposite = ref.getEOpposite();
                    if (!graphicalChildren.contains(oldChildrenEntry.getValue())) {
                        if (eOpposite != null && !eOpposite.isContainment() && !ref.isContainment()) {
                            RemoveValueRequest rmVa = new RemoveValueRequest(targetElement, ref,
                                    Collections.singletonList(oldChildrenEntry.getValue()));
                            RemoveValueCommand rmCmd = new RemoveValueCommand(rmVa);
                            StringBuilder stringBuilder = new StringBuilder();
                            stringBuilder.append("From handling parent : Remove ");////$NON-NLS-1$
                            stringBuilder.append(Utils.getCorrectLabel(ref));
                            stringBuilder.append(" from ");////$NON-NLS-1$
                            stringBuilder.append(Utils.getCorrectLabel(targetElement));
                            stringBuilder.append(" value ");////$NON-NLS-1$
                            stringBuilder.append(Utils.getCorrectLabel(oldChildrenEntry.getValue()));////$NON-NLS-1$
                            rmCmd.setLabel(stringBuilder.toString());
                            if (rmCmd != null) {
                                cc.compose(rmCmd);
                            }
                        }
                    }
                }
            }
        }
        /*
         * Set semantic
         */
        Set<EObject> newChildren = Sets.newHashSet();
        for (Entry<EReference, EObject> entry : request.getChildrenEReferenceMap().entries()) {
            EReference ref = entry.getKey();
            if (ref != null) {
                EReference eOpposite = ref.getEOpposite();
                if (!graphicalChildren.contains(entry.getValue())) {
                    newChildren.add(entry.getValue());
                    if (eOpposite != null && !eOpposite.isContainment()) {
                        SetDeferredRequest setRq = new SetDeferredRequest(
                                request.getHostRequest().getEditingDomain(), request.getTargetElement(), ref,
                                entry.getValue());
                        DeferredSetValueCommand setCmd = new DeferredSetValueCommand(setRq);
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append("From handling parent : Set deferred");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(entry.getValue()));
                        stringBuilder.append(" from ");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(ref));
                        stringBuilder.append(" value ");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(entry.getValue()));////$NON-NLS-1$
                        setCmd.setLabel(stringBuilder.toString());
                        if (setCmd != null) {
                            cc.compose(setCmd);
                        }
                    }
                }
            }
            if (!newChildren.isEmpty()) {
                handleChangeParentNotificationCommand(request, cc, newChildren);
            }
        }
    }

    /**
     * Create a notification to user to ask him is he want to add its new children as graphical child of its parent group
     * 
     * @param request
     *        {@link InitialContext} {@link IGroupRequest}
     * @param cc
     *        {@link CompositeCommand} to compose new commands
     * @param newChildren
     *        List of all new children
     */
    protected void handleChangeParentNotificationCommand(final IGroupRequest request, CompositeCommand cc,
            Set<EObject> newChildren) {
        /*
         * Create dialog to suggest user to move views
         */
        final IGraphicalEditPart host = request.getHostRequest();
        /*
         * Get editpart of all children
         */
        Iterable<IGroupNotifier> listOfChidren = Iterables.transform(newChildren,
                new Function<EObject, IGroupNotifier>() {

                    public IGroupNotifier apply(EObject arg0) {
                        Collection<IGroupNotifier> notifiers = getListenerRegistry().get(arg0);
                        for (IGroupNotifier notifier : notifiers) {
                            IGraphicalEditPart notifierEditPart = notifier.getHostEditPart();
                            if (notifierEditPart != null) {
                                if (EcoreUtil.isAncestor(host.getNotationView().getDiagram(),
                                        notifierEditPart.getNotationView())) {
                                    return notifier;
                                }
                            }
                        }
                        return null;
                    }
                });
        final Iterable<IGroupNotifier> listOfFilteredChidren = Iterables.filter(listOfChidren,
                Predicates.notNull());
        List<IGroupNotifier> automaticChildren = Lists.newArrayList();
        List<IGroupNotifier> nonAutomaticChildren = Lists.newArrayList();
        /*
         * Dispatch children
         */
        dispatchChildren(request, host, listOfFilteredChidren, automaticChildren, nonAutomaticChildren);
        IGraphicalEditPart hostEditPart = request.getHostRequest();
        /*
         * Command to change graphical parent for element when we can guess graphical parent
         */
        for (IGroupNotifier notifier : automaticChildren) {
            IGraphicalEditPart notifierEditPart = notifier.getHostEditPart();
            IGraphicalEditPart hostCompartmentEditPart = request.getNodeDescpitor()
                    .getCompartmentPartFromView(hostEditPart);
            Request initialRequest = request.getInitialRequest();
            Rectangle hostBounds = null;
            if (initialRequest instanceof ChangeBoundsRequest) {
                hostBounds = Utils.getAbslotueRequestBounds((ChangeBoundsRequest) initialRequest,
                        hostCompartmentEditPart);
            } else {
                hostBounds = Utils.getAbsoluteBounds(hostCompartmentEditPart);
            }
            Rectangle childBounds = Utils.getAbsoluteBounds(notifierEditPart);
            MoveElementsCommand mvCmd = new MoveElementsCommand(
                    new MoveRequest(hostCompartmentEditPart.getNotationView(), notifierEditPart.getNotationView()));
            /*
             * Integrate view into new compartment
             */
            if (mvCmd != null && mvCmd.canExecute()) {
                cc.compose(mvCmd);
            }
            /*
             * Set view to the new location
             */
            SetBoundsCommand setBoundCommand = new SetBoundsCommand(
                    WorkspaceEditingDomainFactory.INSTANCE
                            .getEditingDomain(host.getNotationView().eResource().getResourceSet()),
                    "test", new EObjectAdapter(notifierEditPart.getNotationView()),
                    childBounds.translate(hostBounds.getLocation().negate()));
            if (setBoundCommand != null && setBoundCommand.canExecute()) {
                cc.compose(setBoundCommand);
            }
        }
        /*
         * Create notification for element where we can NOT guess the graphical parent
         */
        if (!nonAutomaticChildren.isEmpty()) {
            /*
             * create runnable to run the command
             */
            ChangeGraphicalParentRunnable changeGraphicalParentRunnable = new ChangeGraphicalParentRunnable(host,
                    request);
            final NotificationBuilder notification = createChangeGraphicalParentNotification(nonAutomaticChildren,
                    changeGraphicalParentRunnable, hostEditPart);
            RunNotificationCommand runNotifCmd = new RunNotificationCommand(
                    request.getHostRequest().getEditingDomain(), "Notification command", //$NON-NLS-1$
                    getWorkspaceFiles(changeGraphicalParentRunnable.getModifiedObject()), notification);//
            cc.compose(runNotifCmd);
        }
    }

    /**
     * Dispatch all children in two category.
     * listOfFilteredChidren will contained all element to automatically add as graphical children
     * nonAutomaticChildren will contained all element to ask the user what to do with
     * 
     * @param request
     * @param host
     * @param listOfFilteredChidren
     * @param automaticChildren
     * @param nonAutomaticChildren
     */
    private void dispatchChildren(final IGroupRequest request, final IGraphicalEditPart host,
            final Iterable<IGroupNotifier> listOfFilteredChidren, List<IGroupNotifier> automaticChildren,
            List<IGroupNotifier> nonAutomaticChildren) {
        for (IGroupNotifier notifier : listOfFilteredChidren) {
            IGraphicalEditPart parentEditPart = getGraphicalParent(notifier.getHostEditPart());
            if (parentEditPart != null) {
                EObject eObject = parentEditPart.resolveSemanticElement();
                if (eObject instanceof ActivityGroup) {
                    ActivityGroup group = (ActivityGroup) eObject;
                    Collection<IGroupNotifier> groupNotifiers = listenners.get(group);
                    if (!groupNotifiers.isEmpty()) {
                        IGroupNotifier myGroupNotifier = groupNotifiers.iterator().next();
                        /*
                         * Is the old container (an activity group) continaing the current moving element
                         */
                        boolean isNewContainerVisuallyIncludeInOldContainer = myGroupNotifier.includes(Utils
                                .getAbslotueRequestBounds((ChangeBoundsRequest) request.getInitialRequest(), host));
                        /*
                         * Can the old container (an activity group) be a model a the current moving element
                         */
                        boolean canTheOldContainerBeAModelParentOfTheNewContainer = myGroupNotifier
                                .getHostGroupDescriptor()
                                .canIBeModelParentOf(host.resolveSemanticElement().eClass());
                        /*
                         * 
                         */
                        boolean canTheNewContainerBeModelParentOfTheOldContianer = request.getNodeDescpitor()
                                .canIBeModelParentOf(host.resolveSemanticElement().eClass());
                        /*
                         * Is the current moving element containing the old container
                         */
                        IGroupNotifier currentElementNotifier = getIGroupNotifier(host);
                        boolean isOldContainerVisuallyIncludeInNewContainer = currentElementNotifier
                                .includes(Utils.getAbsoluteBounds(myGroupNotifier.getHostEditPart()));
                        if (canTheOldContainerBeAModelParentOfTheNewContainer
                                && isNewContainerVisuallyIncludeInOldContainer) {
                            /*
                             * Is going to be a new child of the old container
                             */
                            automaticChildren.add(notifier);
                        } else if (canTheNewContainerBeModelParentOfTheOldContianer
                                && isOldContainerVisuallyIncludeInNewContainer) {
                            /*
                             * Is going to be a new container for the old container
                             */
                        } else {
                            /*
                             * There is no containing relation between the groups
                             */
                            if (currentElementNotifier.getHostGroupDescriptor().getContainmentReferenceFor(
                                    notifier.getHostEditPart().resolveSemanticElement().eClass()) == null) {
                                nonAutomaticChildren.add(notifier);
                            } else {
                                // If containment link automatically add it to new group
                                automaticChildren.add(notifier);
                            }
                        }
                    } else {
                        /*
                         * No notifier where found
                         */
                        nonAutomaticChildren.add(notifier);
                    }
                } else {
                    /*
                     * If there is no container (which is group)
                     */
                    if (!parentEditPart.equals(host)) {
                        automaticChildren.add(notifier);
                    }
                }
            } else {
                DebugUtils.getLog()
                        .error("Unable to retreive graphical parent of " + Utils.getCorrectLabel(notifier), null);
            }
        }
    }

    /**
     * Get the IGroupNotifier of the {@link IGraphicalEditPart} passed in argument
     * 
     * @param host
     * @return
     */
    private IGroupNotifier getIGroupNotifier(final IGraphicalEditPart host) {
        EditPolicy editPolicy = host
                .getEditPolicy(IGroupEditPolicies.GROUP_FRAMEWORK_NOTIFYING_ON_MOVE_EDIT_POLICY);
        if (editPolicy instanceof IGroupNotifier) {
            return (IGroupNotifier) editPolicy;
        } else {
            editPolicy = host.getEditPolicy(IGroupEditPolicies.GROUP_FRAMEWORK_NOTIFYING_ON_CREATION_EDIT_POLICY);
            if (editPolicy instanceof IGroupNotifier) {
                return (IGroupNotifier) editPolicy;
            }
        }
        throw new RuntimeException("Unable to retreive the IGroupNofier of the current group");////$NON-NLS-1$
    }

    /**
     * Get the edit which represent the parent (semantically) of the edit part child passed in argument
     * 
     * @param child
     * @return
     */
    private IGraphicalEditPart getGraphicalParent(IGraphicalEditPart child) {
        IGraphicalEditPart result = child;
        EObject childElement = child.resolveSemanticElement();
        if (child != null) {
            while (childElement == result.resolveSemanticElement()) {
                try {
                    result = (IGraphicalEditPart) result.getParent();
                } catch (ClassCastException e) {
                    return result;
                }
            }
        }
        return result;
    }

    /**
     * Create a notification to ask user if he want to change the graphical parent of some elements
     * 
     * @param listOfFilteredChidren
     * @param changeGraphicalParentRunnable
     * @return
     */
    private NotificationBuilder createChangeGraphicalParentNotification(
            final Iterable<IGroupNotifier> listOfFilteredChidren,
            ChangeGraphicalParentRunnable changeGraphicalParentRunnable, final IGraphicalEditPart host) {
        return new NotificationBuilder().setType(Type.INFO).setAsynchronous(true).setTemporary(true).setDelay(3000)
                .setTitle("Papyrus graphical modification").setComposite(new ICompositeCreator() {

                    public Composite createComposite(Composite parent, FormToolkit toolkit) {
                        return new IntegrateViewToConfigureComposite(parent, SWT.NONE,
                                Lists.newArrayList(Lists.newArrayList(listOfFilteredChidren)),
                                "New elements are visually contained in the current group ("
                                        + Utils.getCorrectLabel(host)
                                        + ").\n Please select the elements you want to integrate into this group figure.");
                    }
                }).addAction(changeGraphicalParentRunnable);
    }

    /**
     * Handle graphical children
     * 
     * @param request
     *        {@link IGroupRequest}
     * @param cc
     *        {@link CompositeCommand} to compose new commands
     * @return The list of all graphical children already handled
     */
    protected List<EObject> handleGraphicalChildren(IGroupRequest request, CompositeCommand cc) {
        /*
         * List of all the graphical children
         */
        List<EObject> graphicalChildren = new ArrayList<EObject>();
        /*
         * Handle graphical children
         */
        //Get graphical children
        Object targetEditPart = request.getTargetElement().getAdapter(IGraphicalEditPart.class);
        IGraphicalEditPart compartementEditPart = null;
        if (targetEditPart instanceof IGroupCompartmentEditPart) {
            compartementEditPart = ((IGraphicalEditPart) targetEditPart);
        } else if (targetEditPart instanceof IGraphicalEditPart) {
            IContainerNodeDescriptor nodeDescpitor = request.getNodeDescpitor();
            if (nodeDescpitor != null) {
                compartementEditPart = nodeDescpitor
                        .getCompartmentPartFromView((IGraphicalEditPart) targetEditPart);
            }
        }
        if (compartementEditPart != null) {
            /*
             * Transform an IGraphicalEditPart to the related GroupNotifyingEditPolicy
             */
            @SuppressWarnings("unchecked")
            Iterable<GroupNotifyingOnMoveEditPolicy> policies = Iterables.transform(
                    compartementEditPart.getChildren(),
                    new Function<IGraphicalEditPart, GroupNotifyingOnMoveEditPolicy>() {

                        public GroupNotifyingOnMoveEditPolicy apply(IGraphicalEditPart from) {
                            EditPolicy editPolicy = from.getEditPolicy(
                                    IGroupEditPolicies.GROUP_FRAMEWORK_NOTIFYING_ON_MOVE_EDIT_POLICY);
                            if (editPolicy instanceof GroupNotifyingOnMoveEditPolicy) {
                                return (GroupNotifyingOnMoveEditPolicy) editPolicy;
                            }
                            return null;
                        }
                    });
            for (final GroupNotifyingOnMoveEditPolicy p : policies) {
                if (p != null) {
                    if (DebugUtils.isDebugging()) {
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append("+++ Work for child ");
                        stringBuilder.append(Utils.getCorrectLabel(p.getEObject()));
                        stringBuilder.append(" +++");
                        DebugUtils.getLog().debug(stringBuilder.toString());
                    }
                    Request initialRequest = request.getInitialRequest();
                    Request auxChReq = null;
                    if (initialRequest instanceof ChangeBoundsRequest) {
                        auxChReq = Utils.getChangeBoundsRequestCopy((ChangeBoundsRequest) initialRequest,
                                p.getHostEditPart());
                    } else {
                        auxChReq = initialRequest;
                    }
                    /*
                     * Save graphical parent
                     */
                    //               auxChReq.getExtendedData().put(GROUP_FRAMEWORK_GRAPHICAL_PARENT, compartementEditPart.resolveSemanticElement());
                    graphicalChildren.add(p.getEObject());
                    Command childCommand = p.getCommand(auxChReq);
                    if (childCommand != null && childCommand.canExecute()) {
                        cc.compose(new CommandProxy(childCommand));
                    }
                }
            }
        }
        return graphicalChildren;
    }

    /**
     * Set and Unset semantic relation with parents
     * 
     * @param request
     *        {@link IGroupRequest}
     * @param cc
     *        {@link CompositeCommand} to compose command
     * @param elementAdapter
     */
    protected void handleSemanticParents(IGroupRequest request, CompositeCommand cc, Object elementAdapter) {
        EObject targetElement = (EObject) elementAdapter;
        Multimap<EReference, EObject> allActualParent = request.getParentEReferenceMap();
        for (Entry<EReference, EObject> entry : Utils.getOldParents(request).entries()) {
            EReference ref = entry.getKey();
            if (ref != null) {
                if (!allActualParent.containsEntry(ref, entry.getValue())) {
                    EReference eOpposite = ref.getEOpposite();
                    if (eOpposite != null && !eOpposite.isContainment() && !eOpposite.isDerived()) {
                        RemoveValueRequest rmVa = new RemoveValueRequest(targetElement, ref,
                                Collections.singletonList(entry.getValue()));
                        RemoveValueCommand rmCmd = new RemoveValueCommand(rmVa);
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append("From handling parent : Remove ");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(entry.getValue()));
                        stringBuilder.append(" from ");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(targetElement));
                        stringBuilder.append(" value ");////$NON-NLS-1$
                        stringBuilder.append(Utils.getCorrectLabel(entry.getValue()));////$NON-NLS-1$
                        rmCmd.setLabel(stringBuilder.toString());
                        if (rmCmd != null) {
                            cc.compose(rmCmd);
                        }
                    }
                    //               }
                }
            }
        }
        /*
         * Set semantic
         * If the EObject has not been already handle as graphical children
         */
        for (Entry<EReference, EObject> entry : request.getParentEReferenceMap().entries()) {
            EReference ref = entry.getKey();
            if (ref != null) {
                EReference eOpposite = ref.getEOpposite();
                if (eOpposite != null && !eOpposite.isContainment() && !ref.isContainment()) {
                    SetDeferredRequest setRq = new SetDeferredRequest(request.getHostRequest().getEditingDomain(),
                            request.getTargetElement(), ref, entry.getValue());
                    DeferredSetValueCommand setCmd = new DeferredSetValueCommand(setRq);
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("From handling parent : Set deferred ");////$NON-NLS-1$
                    stringBuilder.append(Utils.getCorrectLabel(ref));
                    stringBuilder.append(" from ");////$NON-NLS-1$
                    stringBuilder.append(Utils.getCorrectLabel(request.getTargetElement()));
                    stringBuilder.append(" value ");////$NON-NLS-1$
                    stringBuilder.append(Utils.getCorrectLabel(entry.getValue()));////$NON-NLS-1$
                    setCmd.setLabel(stringBuilder.toString());
                    if (setCmd != null) {
                        cc.compose(setCmd);
                    }
                }
            }
        }
    }

    /**
     * Return a list of all IGroupRequestListenner which can be children of the target of the request
     * 
     * @param request
     * @return
     */
    protected Multimap<EReference, IGroupNotifier> fillRequestWithAllPossibleChildren(IGroupRequest request) {
        final Multimap<EReference, IGroupNotifier> result = fillReqestWithReferendedElement(request, false, false);
        /**
         * TODO filter graphical parent which currently moving
         * I1 in ActPart1
         * ActPart1 move into ActPart2
         * I1 should only reference ActPart1
         */
        /*
         * Debug
         */
        DebugUtils.displayMultipmapDebug(CHILDREN_REFERENCES_ARE, request.getChildrenEReferenceMap());
        return result;
    }

    public EObject getPossibleModelParent(IGroupRequest request) {
        Multimap<EReference, IGroupNotifier> parentsMap = fillReqestWithReferendedElement(request, true, true);
        List<IGroupNotifier> parents = Lists.newArrayList(parentsMap.values());
        Collections.sort(parents);
        if (!parents.isEmpty()) {
            return parents.get(0).getEObject();
        }
        return request.getHostRequest().resolveSemanticElement();
    }

    /**
     * Return only current displayed listener
     * 
     * @author adaussy
     * 
     */
    private static class ActiveListener implements Predicate<IGroupNotifier> {

        private Diagram currentDiagramDisplayed;

        public ActiveListener(Diagram currentDiagramDisplayed) {
            super();
            this.currentDiagramDisplayed = currentDiagramDisplayed;
            Assert.isNotNull(currentDiagramDisplayed);
        }

        public boolean apply(IGroupNotifier input) {
            IGraphicalEditPart host = input.getHostEditPart();
            if (host != null) {
                View primaryView = host.getPrimaryView();
                if (primaryView != null) {
                    return currentDiagramDisplayed.equals(primaryView.getDiagram());
                }
            }
            return false;
        }
    }

    /**
     * Get all the element in references which are included or include (depending of the parameter include)
     * 
     * @param request
     *        {@link IGroupRequest}
     * @param newBounds
     *        New bounds of the elements
     * @param references
     *        All references to take into account
     * @param eReferenceMapToFillInRequest
     *        Map in the request to fill
     * @param result
     *        {@link Map} which link a {@link EReference} to a {@link IGroupNotifier}
     * @param containementOnly
     *        true if we are looking for containing references only
     */
    protected void getReferenceElements(IGroupRequest request, final Rectangle newBounds,
            final List<EReference> references, Multimap<EReference, Element> eReferenceMapToFillInRequest,
            Multimap<EReference, IGroupNotifier> result, boolean include, boolean containementOnly,
            Map<EStructuralFeature, EStructuralFeature> parentOpositeFeature) {
        Iterable<IGroupNotifier> activeListeners = Iterables.filter(getListenerRegistry().values(),
                new ActiveListener(getCurrentlyDisplayedDiagram(request)));
        for (IGroupNotifier input : activeListeners) {
            EObject inputEObject = input.getEObject();
            if (inputEObject == null || !(inputEObject instanceof Element)) {
                continue;
            }
            Object adapter = request.getTargetElement().getAdapter(EObject.class);
            //         EObject targetElement = null;
            //         if(adapter instanceof EObject) {
            //            targetElement = (EObject)adapter;
            //         }
            if (inputEObject.equals(adapter)) {
                continue;
            }
            EReference refenceFounded = null;
            for (EReference ref : references) {
                EClass refType = ref.getEReferenceType();
                EClass eoBjectType = inputEObject.eClass();
                if (refType.isSuperTypeOf(eoBjectType)) {
                    refenceFounded = ref;
                    break;
                }
            }
            if (refenceFounded != null) {
                if ((include && input.includes(newBounds)) || (!include && input.isIncludedIn(newBounds))) {
                    if (containementOnly && parentOpositeFeature.get(refenceFounded) instanceof EReference
                            && !((EReference) parentOpositeFeature.get(refenceFounded)).isContainment()) {
                        continue;
                    }
                    eReferenceMapToFillInRequest.put(refenceFounded, (Element) inputEObject);
                    result.put(refenceFounded, input);
                }
            }
        }
    }

    /**
     * Return the currently displayed diagram
     * 
     * @param request
     * @return
     */
    protected Diagram getCurrentlyDisplayedDiagram(IGroupRequest request) {
        IGraphicalEditPart graph = request.getHostRequest();
        if (graph != null) {
            Object m = graph.getModel();
            if (m instanceof View) {
                View v = (View) m;
                return v.getDiagram();
            }
        }
        throw new RuntimeException("Unable to get the current diagram displayed");////$NON-NLS-1$
    }

    /**
     * Return the list of all {@link IGroupNotifier} which can be parent of the target of the request
     * 
     * @param request
     * @return
     */
    protected Multimap<EReference, IGroupNotifier> fillRequestWithAllPossibleParent(IGroupRequest request) {
        final Multimap<EReference, IGroupNotifier> result = fillReqestWithReferendedElement(request, true, false);
        /*
         * Debug
         */
        DebugUtils.displayMultipmapDebug(ALL_PARENT_REFERENCES_ARE, request.getParentEReferenceMap());
        return result;
    }

    protected Multimap<EReference, IGroupNotifier> fillReqestWithReferendedElement(IGroupRequest request,
            boolean lookingForParent, boolean onlyContainment) {
        final Rectangle newBounds = getInitalTargetRequestNewBounds(request);
        final Multimap<EReference, IGroupNotifier> result = ArrayListMultimap.create();
        if (request.getNodeDescpitor() == null) {
            return result;
        }
        List<EReference> references = null;
        if (lookingForParent) {
            references = request.getNodeDescpitor().getParentReferences();
        } else {
            references = request.getNodeDescpitor().getChildrenReferences();
        }
        final Multimap<EReference, IGroupNotifier> auxResult = ArrayListMultimap.create();
        final Multimap<EReference, Element> eReferenceLookedForMap = ArrayListMultimap.create();
        getReferenceElements(request, newBounds, references, eReferenceLookedForMap, auxResult, lookingForParent,
                onlyContainment,
                lookingForParent ? request.getNodeDescpitor().getParentEOppositeReferences() : null);
        /*
         * Filter ancestors
         */
        for (EReference ref : eReferenceLookedForMap.keySet()) {
            /*
             * Filter descendant
             * Example :
             * 1 - ActPart1 include in Act1 then Act1 disappear
             * 2 - ActPart1 include in ActPart2 then ActPart1 disappear
             */
            Object adapter = request.getTargetElement().getAdapter(EObject.class);
            if (adapter instanceof Element) {
                Element element = (Element) adapter;
                Predicate<Element> composedPredicate = Predicates.and(new SameContainerFilter(element),
                        lookingForParent ? new DescendantsFilter(eReferenceLookedForMap.values())
                                : new AncestorFilter(eReferenceLookedForMap.values()));
                Collection<Element> filteredCollection = Collections2.filter(eReferenceLookedForMap.get(ref),
                        composedPredicate);
                if (lookingForParent) {
                    request.getParentEReferenceMap().putAll(ref, filteredCollection);
                } else {
                    request.getChildrenEReferenceMap().putAll(ref, filteredCollection);
                }
            }
        }
        for (EReference ref : auxResult.keySet()) {
            /*
             * Filter descendant
             * Example :
             * 1 - ActPart1 include in Act1 then Act1 disappear
             * 2 - ActPart1 include in ActPart2 then ActPart1 disappear
             */
            Iterable<IGroupNotifier> resultCollection = Iterables.filter(auxResult.get(ref),
                    new DescendantsFilterIGroupNotifier(auxResult.values()));
            result.putAll(ref, resultCollection);
        }
        return result;
    }

    /**
     * Get the absolute bounds of the target of the request
     * 
     * @param request
     * @return
     */
    public static Rectangle getInitalTargetRequestNewBounds(final IGroupRequest request) {
        Request initialRequest = request.getInitialRequest();
        if (initialRequest instanceof ChangeBoundsRequest) {
            return Utils.getAbslotueRequestBounds((ChangeBoundsRequest) initialRequest, request.getHostRequest());
        } else if (initialRequest instanceof CreateViewRequest) {
            return Utils.getAbslotueRequestBounds((CreateViewRequest) initialRequest);
        }
        throw new RuntimeException(UNABLE_TO_GET_THE_INTIAL_TARGET_REQUEST_BOUNDS);
    }

    /**
     * Convenience method to get a list of workspaces files associated with <code>eObject</code>.
     * 
     * @param eObject
     *        the model object, may be <code>null</code>
     * @return the list of {@link IFile}s
     */
    protected static List getWorkspaceFiles(EObject eObject) {
        List result = new ArrayList();
        if (eObject != null) {
            Resource resource = eObject.eResource();
            if (resource != null) {
                IFile file = WorkspaceSynchronizer.getFile(resource);
                if (file != null) {
                    result.add(file);
                }
            }
        }
        return result;
    }

    /**
     * Convenience method to get a list of workspaces files associated with {@link EObject}s in <code>eObject</code>.
     * 
     * @param eObjects
     *        the list of model object
     * @return the list of {@link IFile}s
     */
    protected static List getWorkspaceFiles(List eObjects) {
        List result = new ArrayList();
        for (Iterator i = eObjects.iterator(); i.hasNext();) {
            Object next = i.next();
            if (next instanceof EObject) {
                Resource resource = ((EObject) next).eResource();
                if (resource != null) {
                    IFile file = WorkspaceSynchronizer.getFile(resource);
                    if (file != null) {
                        result.add(file);
                    }
                }
            }
        }
        return result;
    }

    /**
     * @return the listenners
     */
    public Multimap<EObject, IGroupNotifier> getListenerRegistry() {
        return listenners;
    }
}