| /******************************************************************************* |
| * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES and others. |
| * 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.tree.business.internal.dialect; |
| |
| import java.text.MessageFormat; |
| import java.util.Collection; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.emf.transaction.util.TransactionUtil; |
| import org.eclipse.sirius.business.api.dialect.AbstractRepresentationDialectServices; |
| import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQuery; |
| import org.eclipse.sirius.business.api.query.DRepresentationElementQuery; |
| import org.eclipse.sirius.business.api.query.EObjectQuery; |
| import org.eclipse.sirius.business.api.query.IdentifiedElementQuery; |
| import org.eclipse.sirius.business.api.session.CustomDataConstants; |
| import org.eclipse.sirius.business.api.session.Session; |
| import org.eclipse.sirius.business.api.session.SessionManager; |
| import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException; |
| import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter; |
| import org.eclipse.sirius.common.tools.api.util.StringUtil; |
| import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor; |
| import org.eclipse.sirius.tools.api.command.DCommand; |
| import org.eclipse.sirius.tools.api.interpreter.InterpreterRegistry; |
| import org.eclipse.sirius.tools.api.interpreter.InterpreterUtil; |
| import org.eclipse.sirius.tree.DTree; |
| import org.eclipse.sirius.tree.DTreeElement; |
| import org.eclipse.sirius.tree.DTreeElementSynchronizer; |
| import org.eclipse.sirius.tree.DTreeItem; |
| import org.eclipse.sirius.tree.TreeFactory; |
| import org.eclipse.sirius.tree.business.api.interaction.DTreeUserInteraction; |
| import org.eclipse.sirius.tree.business.internal.dialect.common.viewpoint.GlobalContext; |
| import org.eclipse.sirius.tree.business.internal.dialect.description.TreeInterpretedExpressionQuery; |
| import org.eclipse.sirius.tree.business.internal.refresh.DTreeElementSynchronizerSpec; |
| import org.eclipse.sirius.tree.description.TreeDescription; |
| import org.eclipse.sirius.tree.tools.internal.Messages; |
| import org.eclipse.sirius.tree.tools.internal.command.TreeCommandFactory; |
| import org.eclipse.sirius.viewpoint.DRepresentation; |
| import org.eclipse.sirius.viewpoint.DSemanticDecorator; |
| import org.eclipse.sirius.viewpoint.SiriusPlugin; |
| import org.eclipse.sirius.viewpoint.description.RepresentationDescription; |
| import org.eclipse.sirius.viewpoint.description.RepresentationExtensionDescription; |
| import org.eclipse.sirius.viewpoint.description.Viewpoint; |
| |
| import com.google.common.collect.Sets; |
| |
| /** |
| * The {@link AbstractRepresentationDialectServices} implementation for the Tree |
| * dialect. |
| * |
| * @author pcdavid |
| */ |
| public class TreeDialectServices extends AbstractRepresentationDialectServices { |
| @Override |
| protected boolean isSupported(RepresentationDescription description) { |
| return description instanceof TreeDescription; |
| } |
| |
| @Override |
| protected boolean isSupported(DRepresentation representation) { |
| return representation instanceof DTree; |
| } |
| |
| @Override |
| public DRepresentation createRepresentation(String name, EObject semantic, RepresentationDescription description, IProgressMonitor monitor) { |
| DTree tree = null; |
| try { |
| monitor.beginTask(MessageFormat.format(Messages.TreeDialectServices_createTree, name), 11); |
| monitor.subTask(MessageFormat.format(Messages.TreeDialectServices_createTree, name)); |
| final Session session = SessionManager.INSTANCE.getSession(semantic); |
| final EditingDomain domain = session.getTransactionalEditingDomain(); |
| /* |
| * Let's check if the description resource is in the session |
| * resource set. |
| */ |
| /* |
| * FIXME we should certainly not remove from the previous resource |
| * set. The viewpoint registry for instance has is own resource set |
| * ! |
| */ |
| final Resource descriptionRes = description.eResource(); |
| if (!domain.getResourceSet().getResources().contains(descriptionRes)) { |
| domain.getResourceSet().getResources().add(descriptionRes); |
| } |
| |
| tree = TreeFactory.eINSTANCE.createDTree(); |
| tree.setName(name); |
| tree.setDescription((TreeDescription) description); |
| tree.setTarget(semantic); |
| monitor.worked(1); |
| |
| refresh(tree, new SubProgressMonitor(monitor, 10)); |
| } finally { |
| monitor.done(); |
| } |
| return tree; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void initRepresentations(Viewpoint vp, EObject semantic) { |
| super.initRepresentations(semantic, vp, TreeDescription.class); |
| } |
| |
| @Override |
| public void initRepresentations(Viewpoint vp, EObject semantic, IProgressMonitor monitor) { |
| super.initRepresentations(semantic, vp, TreeDescription.class, monitor); |
| } |
| |
| @Override |
| protected <T extends RepresentationDescription> void initRepresentationForElement(T representationDescription, EObject semanticElement, IProgressMonitor monitor) { |
| if (representationDescription instanceof TreeDescription) { |
| TreeDescription treeDescription = (TreeDescription) representationDescription; |
| if (shouldInitializeRepresentation(semanticElement, treeDescription, treeDescription.getDomainClass())) { |
| |
| final ModelAccessor modelAccessor = SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(semanticElement); |
| final TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(semanticElement); |
| |
| if (modelAccessor.eInstanceOf(semanticElement, treeDescription.getDomainClass())) { |
| boolean canCreate = true; |
| if (treeDescription.getPreconditionExpression() != null && !StringUtil.isEmpty(treeDescription.getPreconditionExpression())) { |
| try { |
| canCreate = InterpreterUtil.getInterpreter(semanticElement).evaluateBoolean(semanticElement, treeDescription.getPreconditionExpression()); |
| } catch (final EvaluationException e) { |
| canCreate = false; |
| } |
| } |
| if (canCreate) { |
| try { |
| monitor.beginTask(MessageFormat.format(Messages.TreeDialectServices_initializeTree, new IdentifiedElementQuery(representationDescription).getLabel()), 1); |
| final TreeCommandFactory treeCommandFactory = new TreeCommandFactory(domain); |
| treeCommandFactory.setModelAccessor(modelAccessor); |
| DCommand command = treeCommandFactory.buildCreateTreeFromDescription(treeDescription, semanticElement, new SubProgressMonitor(monitor, 1)); |
| domain.getCommandStack().execute(command); |
| } finally { |
| monitor.done(); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public DRepresentation copyRepresentation(final DRepresentation representation, final String name, final Session session, final IProgressMonitor monitor) { |
| DRepresentation newRepresentation = super.copyRepresentation(representation, name, session, monitor); |
| /* associate the one */ |
| session.getServices().putCustomData(CustomDataConstants.DREPRESENTATION, ((DSemanticDecorator) representation).getTarget(), newRepresentation); |
| return newRepresentation; |
| } |
| |
| /** |
| * Initializes the Representation described by the given description, |
| * according the the given target value. |
| * |
| * @param description |
| * the RepresentationDescription describing the representation to |
| * initialize |
| * @param target |
| * the semantic target to use for initialize this representation |
| */ |
| protected void initRepresentation(RepresentationDescription description, EObject target) { |
| // TODO |
| } |
| |
| @Override |
| public void refresh(DRepresentation representation, boolean fullRefresh, IProgressMonitor monitor) { |
| try { |
| monitor.beginTask(Messages.TreeDialectServices_treeRefresh, 1); |
| if (canRefresh(representation)) { |
| refreshTree((DTree) representation, fullRefresh, monitor); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| @Override |
| public RepresentationDescription getDescription(DRepresentation representation) { |
| if (isSupported(representation)) { |
| return ((DTree) representation).getDescription(); |
| } else { |
| return null; |
| } |
| } |
| |
| private void refreshTree(DTree tree, boolean fullRefresh, IProgressMonitor monitor) { |
| Session session = SessionManager.INSTANCE.getSession(tree.getTarget()); |
| IInterpreter interpreter = SiriusPlugin.getDefault().getInterpreterRegistry().getInterpreter(tree.getTarget()); |
| InterpreterRegistry.prepareImportsFromSession(interpreter, session); |
| ModelAccessor accessor = SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(tree.getTarget()); |
| |
| DTreeUserInteraction interaction = new DTreeUserInteraction(tree, new GlobalContext(accessor, session.getInterpreter(), session.getSemanticResources())); |
| interaction.refreshContent(fullRefresh, new SubProgressMonitor(monitor, 1)); |
| |
| } |
| |
| @Override |
| public boolean canCreate(EObject semantic, RepresentationDescription desc) { |
| boolean result = false; |
| if (semantic != null && isSupported(desc)) { |
| TreeDescription treeDesc = (TreeDescription) desc; |
| ModelAccessor accessor = SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(semantic); |
| if (accessor != null) { |
| result = checkDomainClass(accessor, semantic, treeDesc.getDomainClass()); |
| } |
| result = result && checkPrecondition(semantic, treeDesc.getPreconditionExpression()); |
| } |
| return result; |
| } |
| |
| @Override |
| public IInterpretedExpressionQuery createInterpretedExpressionQuery(EObject target, EStructuralFeature feature) { |
| return new TreeInterpretedExpressionQuery(target, feature); |
| } |
| |
| @Override |
| public boolean handles(RepresentationDescription representationDescription) { |
| return representationDescription instanceof TreeDescription; |
| } |
| |
| @Override |
| public boolean handles(RepresentationExtensionDescription representationExtensionDescription) { |
| return false; |
| } |
| |
| @Override |
| public void refreshImpactedElements(DRepresentation representation, Collection<Notification> notifications, IProgressMonitor monitor) { |
| try { |
| monitor.beginTask(Messages.DTreeUserInteraction_treeRefresh, 10); |
| DTree tree = (DTree) representation; |
| IInterpreter interpreter = SiriusPlugin.getDefault().getInterpreterRegistry().getInterpreter(tree.getTarget()); |
| ModelAccessor accessor = SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(representation); |
| |
| Set<DTreeElement> dTreeElements = getTreeElementsToRefresh(notifications, tree); |
| monitor.worked(2); |
| DTreeElementSynchronizer synchronizer = new DTreeElementSynchronizerSpec(interpreter, accessor); |
| IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 8); |
| try { |
| subMonitor.beginTask(Messages.TreeDialectServices_refreshImpactedElements, dTreeElements.size()); |
| for (DTreeElement dTreeElement : dTreeElements) { |
| if (dTreeElement instanceof DTreeItem) { |
| synchronizer.refresh((DTreeItem) dTreeElement); |
| } |
| subMonitor.worked(1); |
| } |
| } finally { |
| subMonitor.done(); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| private Set<DTreeElement> getTreeElementsToRefresh(Collection<Notification> notifications, DTree tree) { |
| Set<DTreeElement> treeElementsToRefresh = Sets.newHashSet(); |
| Session session = new org.eclipse.sirius.business.api.query.EObjectQuery(tree.getTarget()).getSession(); |
| if (session != null) { |
| ECrossReferenceAdapter xref = session.getSemanticCrossReferencer(); |
| // Deal with each notifier only one time. |
| Set<EObject> alreadyDoneNotifiers = Sets.newHashSet(); |
| for (Notification notification : notifications) { |
| Object notifier = notification.getNotifier(); |
| if (notifier instanceof EObject) { |
| EObject eObjectNotifier = (EObject) notifier; |
| if (alreadyDoneNotifiers.add(eObjectNotifier)) { |
| treeElementsToRefresh.addAll(getTreeElementsToRefresh(eObjectNotifier, tree, xref)); |
| } |
| } |
| } |
| } |
| return treeElementsToRefresh; |
| } |
| |
| private Set<DTreeElement> getTreeElementsToRefresh(EObject notifier, DTree tree, ECrossReferenceAdapter xref) { |
| Set<DTreeElement> treeElementsToRefresh = Sets.newHashSet(); |
| Collection<EObject> inverseReferencers = new EObjectQuery(notifier, xref).getInverseReferences(REPRESENTATION_ELEMENTS_INVERSE_REFERENCES); |
| for (EObject inverseReferencer : inverseReferencers) { |
| if (inverseReferencer instanceof DTreeElement) { |
| DTreeElement treeElement = (DTreeElement) inverseReferencer; |
| if (isContainedWithinCurrentTree(treeElement, tree)) { |
| treeElementsToRefresh.add(treeElement); |
| } |
| } |
| } |
| return treeElementsToRefresh; |
| } |
| |
| private boolean isContainedWithinCurrentTree(DTreeElement treeElement, DTree tree) { |
| return tree == new DRepresentationElementQuery(treeElement).getParentRepresentation(); |
| } |
| } |