org.eclipse.sirius.diagram.business.internal.experimental.sync.AbstractSynchronizerHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.business.internal.experimental.sync.AbstractSynchronizerHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2010 THALES GLOBAL SERVICES.
 * 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:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.diagram.business.internal.experimental.sync;

import java.util.Collection;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.common.tools.DslCommonPlugin;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DSemanticDiagram;
import org.eclipse.sirius.diagram.DragAndDropTarget;
import org.eclipse.sirius.diagram.business.api.query.DiagramElementMappingQuery;
import org.eclipse.sirius.diagram.business.api.query.EObjectQuery;
import org.eclipse.sirius.diagram.description.DiagramElementMapping;
import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.base.collect.MultipleCollection;
import org.eclipse.sirius.tools.api.interpreter.InterpreterUtil;
import org.eclipse.sirius.tools.api.profiler.SiriusTasksKey;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;

/**
 * A common helper for nodes and edges.
 * 
 * @author mchauvin
 */
public abstract class AbstractSynchronizerHelper {

    /** the semantic diagram. */
    protected final DSemanticDiagram diagram;

    /** the model accessor. **/
    protected ModelAccessor accessor;

    /** the interpreter. */
    protected final IInterpreter interpreter;

    /** the session. */
    protected Session session;

    /** the main synchronizer. */
    protected DDiagramSynchronizer sync;

    /**
     * comes from tool ?.
     */
    protected boolean tool;

    /**
     * A cache for candidates common to all mapping with empty semantic
     * candidates expression (i.e. eAllContents() from root) and with same
     * domainClass.
     */
    private Multimap<String, EObject> candidatesMap = LinkedHashMultimap.create();

    /**
     * Constructor.
     * 
     * @param sync
     *            the main synchronizer
     * @param accessor
     *            the model accessor
     * @param diagram
     *            the semantic diagram
     */
    public AbstractSynchronizerHelper(final DDiagramSynchronizer sync, final DSemanticDiagram diagram,
            final ModelAccessor accessor) {
        this.diagram = diagram;
        this.accessor = accessor;
        this.session = new EObjectQuery(diagram.getTarget()).getSession();
        if (session == null) {
            this.session = new EObjectQuery(diagram).getSession();
        }
        this.interpreter = session != null ? session.getInterpreter()
                : InterpreterUtil.getInterpreter(diagram.getTarget());
        this.sync = sync;
        this.tool = false;
    }

    /**
     * Check if the target of this decorator is not null and is in a eResource.
     * 
     * @param decorator
     *            The decorator to check
     * @return true if the target is OK, false otherwise.
     */
    public static boolean isTargetDying(final DSemanticDecorator decorator) {
        return decorator.getTarget() != null
                && (decorator.getTarget().eContainer() != null || decorator.getTarget().eResource() != null);
    }

    /**
     * 
     * Evaluate the semantic candidates for the given context.
     * 
     * @param container
     *            the container of the potential views.
     * @param mapping
     *            the mapping of the potential candidates.
     * @return a collection of semantic candidates.
     */
    protected Collection<EObject> evaluateCandidateExpression(final DragAndDropTarget container,
            final DiagramElementMapping mapping) {
        return new DiagramElementMappingQuery(mapping).evaluateCandidateExpression(diagram, interpreter, container);
    }

    /**
     * Get all candidates corresponding to the the given mapping in the current
     * session.
     * 
     * @param mapping
     *            mapping to use
     * @return candidates
     */
    protected Collection<EObject> getAllCandidates(DiagramElementMapping mapping) {
        final Collection<EObject> semantics = new MultipleCollection<EObject>();

        Option<String> domainClass = new DiagramElementMappingQuery(mapping).getDomainClass();
        if (domainClass.some()) {
            if (candidatesMap.containsKey(domainClass.get())) {
                semantics.addAll(candidatesMap.get(domainClass.get()));
            } else {
                for (final Resource resource : session.getSemanticResources()) {
                    for (final EObject root : resource.getContents()) {
                        semantics.addAll(this.accessor.eAllContents(root, domainClass.get()));
                    }
                }
                candidatesMap.putAll(domainClass.get(), semantics);
            }
        }
        return semantics;
    }

    /**
     * .
     * 
     * @param container
     *            .
     * @param mapping
     *            .
     * @return .
     */
    protected Collection<EObject> getPreviousSemanticsElements(DragAndDropTarget container,
            DiagramElementMapping mapping) {
        Collection<EObject> transformed = Collections2.transform(
                sync.getPreviousDiagramElements(container, mapping), new Function<DDiagramElement, EObject>() {
                    public EObject apply(final DDiagramElement from) {
                        return from.getTarget();
                    }
                });
        return ImmutableSet.copyOf(
                Collections2.filter(transformed, Predicates.and(Predicates.notNull(), new Predicate<EObject>() {
                    // We don't keep semantic element that is invalid
                    public boolean apply(final EObject input) {
                        return (input.eContainer() != null && input.eContainer().eResource() != null)
                                || input.eResource() != null;
                    }
                })));
    }

    /**
     * Get the semantic candidates for the given context.
     * 
     * @param container
     *            the container of future views created from potential
     *            candidates.
     * @param mapping
     *            the current mapping
     * @return candidates
     */
    protected Iterable<EObject> getSemanticCandidates(DragAndDropTarget container, DiagramElementMapping mapping) {
        DslCommonPlugin.PROFILER.startWork(SiriusTasksKey.GET_NODE_CANDIDATES_KEY);
        Iterable<EObject> semantics = Lists.newArrayList();
        boolean synchronizedAndCreateElement = new DiagramElementMappingQuery(mapping)
                .isSynchronizedAndCreateElement(diagram);
        synchronizedAndCreateElement = tool || synchronizedAndCreateElement;
        if (new DiagramElementMappingQuery(mapping).hasCandidatesExpression()) {
            final Collection<EObject> allCandidates = evaluateCandidateExpression(container, mapping);
            if (synchronizedAndCreateElement) {
                /* Check domain class */
                final Option<String> domainClassOption = new DiagramElementMappingQuery(mapping).getDomainClass();
                if (domainClassOption.some()) {
                    Predicate<EObject> domainClass = new Predicate<EObject>() {
                        public boolean apply(EObject input) {
                            return accessor.eInstanceOf(input, domainClassOption.get());
                        }
                    };
                    semantics = Iterables.concat(semantics, Iterables.filter(allCandidates, domainClass));
                }
            } else {
                sync.forceRetrieve();
                final Collection<EObject> previousSemanticsElements = getPreviousSemanticsElements(container,
                        mapping);
                sync.resetforceRetrieve();
                final Predicate<EObject> stillCandidate = new Predicate<EObject>() {
                    public boolean apply(final EObject input) {
                        return allCandidates.contains(input);
                    }
                };

                final Collection<EObject> keeped = ImmutableSet
                        .copyOf(Collections2.filter(previousSemanticsElements, stillCandidate));
                semantics = Iterables.concat(semantics, keeped);
            }
        } else {
            if (synchronizedAndCreateElement) {
                semantics = Iterables.concat(semantics, getAllCandidates(mapping));
            } else {
                sync.forceRetrieve();
                semantics = Iterables.concat(semantics, getPreviousSemanticsElements(container, mapping));
                sync.resetforceRetrieve();
            }
        }
        DslCommonPlugin.PROFILER.stopWork(SiriusTasksKey.GET_NODE_CANDIDATES_KEY);
        return semantics;
    }

    public void setTool(boolean b) {
        tool = b;
    }

}