blob: 6b2737249275d734dbd610458cf2499daf4197f7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2021 THALES GLOBAL SERVICES.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.diagram.business.internal.metamodel.helper;
import java.util.Collections;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.sirius.business.api.logger.RuntimeLoggerManager;
import org.eclipse.sirius.common.tools.DslCommonPlugin;
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.interpreter.IInterpreterSiriusVariables;
import org.eclipse.sirius.common.tools.api.util.StringUtil;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DNode;
import org.eclipse.sirius.diagram.DNodeListElement;
import org.eclipse.sirius.diagram.DiagramFactory;
import org.eclipse.sirius.diagram.NodeStyle;
import org.eclipse.sirius.diagram.ResizeKind;
import org.eclipse.sirius.diagram.business.internal.metamodel.description.extensions.INodeMappingExt;
import org.eclipse.sirius.diagram.business.internal.metamodel.description.operations.AbstractNodeMappingSpecOperations;
import org.eclipse.sirius.diagram.description.NodeMapping;
import org.eclipse.sirius.diagram.description.style.NodeStyleDescription;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.base.Options;
import org.eclipse.sirius.tools.api.profiler.SiriusTasksKey;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
import org.eclipse.sirius.viewpoint.Style;
import org.eclipse.sirius.viewpoint.description.style.StyleDescription;
import org.eclipse.sirius.viewpoint.description.style.StylePackage;
/**
* Utility class to factor customizations for ContainerMapping and related.
*
* @author pcdavid
*/
public final class NodeMappingHelper {
private IInterpreter interpreter;
private StyleHelper styleHelper;
/**
* Create the helper.
*
* @param interpreter
* interpreter used to evaluate expressions.
*/
public NodeMappingHelper(IInterpreter interpreter) {
this.interpreter = interpreter;
this.styleHelper = new StyleHelper(interpreter);
}
/**
* Implementation of {@link NodeMapping#createNode(EObject, EObject, DDiagram)}.
*
* @param self
* the node mapping.
* @param modelElement
* the semantic element.
* @param container
* the semantic container of the element.
* @param diagram
* the diagram.
* @return the node created.
*/
public DNode createNode(INodeMappingExt self, EObject modelElement, EObject container, DDiagram diagram) {
final DNode newNode = DiagramFactory.eINSTANCE.createDNode();
// getting the right style description : default or conditional
final NodeStyleDescription style = (NodeStyleDescription) new MappingWithInterpreterHelper(interpreter).getBestStyleDescription(self, modelElement, newNode, container, diagram);
newNode.setTarget(modelElement);
newNode.setActualMapping(self);
DiagramElementMappingHelper.refreshSemanticElements(self, newNode, interpreter);
interpreter.setVariable(IInterpreterSiriusVariables.DIAGRAM, diagram);
interpreter.setVariable(IInterpreterSiriusVariables.VIEW, newNode);
if (style != null && style.getLabelExpression() != null) {
try {
final String name = interpreter.evaluateString(modelElement, style.getLabelExpression());
newNode.setName(name);
} catch (final EvaluationException e) {
RuntimeLoggerManager.INSTANCE.error(style, StylePackage.eINSTANCE.getBasicLabelStyleDescription_LabelExpression(), e);
}
}
if (style != null) {
newNode.setResizeKind(style.getResizeKind());
styleHelper.setComputedSize(newNode, style);
}
final NodeStyle bestStyle = (NodeStyle) new MappingWithInterpreterHelper(interpreter).getBestStyle(self, modelElement, newNode, container, diagram);
if (bestStyle != null) {
newNode.setOwnedStyle(bestStyle);
}
MappingWithInterpreterHelper.addDoneNode(self, newNode);
interpreter.unSetVariable(IInterpreterSiriusVariables.VIEW);
interpreter.unSetVariable(IInterpreterSiriusVariables.DIAGRAM);
/*
* Iterate over the border mapping of the node to initialize the border nodes.
*/
AbstractNodeMappingSpecOperations.createBorderingNodes(self, modelElement, newNode, Collections.EMPTY_LIST, diagram);
if (newNode.getOwnedStyle() != null) {
Option<NodeStyle> noPreviousStyle = Options.newNone();
new StyleHelper(interpreter).refreshStyle(newNode.getOwnedStyle(), noPreviousStyle);
}
return newNode;
}
/**
* Implementation of {@link NodeMapping#updateNode(DNode)}.
*
* @param self
* the node mapping.
* @param node
* the node to update.
*/
public void updateNode(NodeMapping self, DNode node) {
final EObject modelElement = node.getTarget();
final DSemanticDecorator container = (DSemanticDecorator) node.eContainer();
NodeStyleDescription style = null;
// getting the right style description : default or conditional
DDiagram parentDiagram = node.getParentDiagram();
if (container != null) {
style = (NodeStyleDescription) new MappingWithInterpreterHelper(interpreter).getBestStyleDescription(self, modelElement, node, container.getTarget(), parentDiagram);
}
if (style != null && style.getLabelExpression() != null) {
try {
interpreter.setVariable(IInterpreterSiriusVariables.DIAGRAM, parentDiagram);
interpreter.setVariable(IInterpreterSiriusVariables.VIEW, node);
final String name = interpreter.evaluateString(modelElement, style.getLabelExpression());
node.setName(name);
} catch (final EvaluationException e) {
RuntimeLoggerManager.INSTANCE.error(style, StylePackage.eINSTANCE.getBasicLabelStyleDescription_LabelExpression(), e);
} finally {
interpreter.unSetVariable(IInterpreterSiriusVariables.DIAGRAM);
interpreter.unSetVariable(IInterpreterSiriusVariables.VIEW);
}
}
if (style != null && style.getTooltipExpression() != null) {
try {
interpreter.setVariable(IInterpreterSiriusVariables.DIAGRAM, parentDiagram);
interpreter.setVariable(IInterpreterSiriusVariables.VIEW, node);
final String tooltip = interpreter.evaluateString(modelElement, style.getTooltipExpression());
node.setTooltipText(tooltip);
} catch (final EvaluationException e) {
RuntimeLoggerManager.INSTANCE.error(style, StylePackage.eINSTANCE.getTooltipStyleDescription_TooltipExpression(), e);
} finally {
interpreter.unSetVariable(IInterpreterSiriusVariables.DIAGRAM);
interpreter.unSetVariable(IInterpreterSiriusVariables.VIEW);
}
}
/*
* Getting the node size
*/
if (node.getResizeKind() == ResizeKind.NONE_LITERAL) {
styleHelper.setComputedSize(node, style);
}
// semantic elements
DiagramElementMappingHelper.refreshSemanticElements(self, node, interpreter);
EObject containerVariable = null;
if (node.eContainer() instanceof DSemanticDecorator) {
containerVariable = ((DSemanticDecorator) node.eContainer()).getTarget();
}
final StyleDescription bestStyleDescription = new MappingWithInterpreterHelper(interpreter).getBestStyleDescription(self, modelElement, node, containerVariable, parentDiagram);
Style bestStyle = node.getStyle();
if ((bestStyle == null || bestStyle.getDescription() != bestStyleDescription) && bestStyleDescription != null) {
bestStyle = styleHelper.createStyle(bestStyleDescription);
}
styleHelper.setAndRefreshStyle(node, node.getStyle(), bestStyle);
MappingWithInterpreterHelper.addDoneNode(self, node);
}
/**
* Implementation of {@link NodeMapping#createListElement(EObject)}.
*
* @param self
* the node mapping.
* @param modelElement
* the semantic model element.
* @param diagram
* the diagram.
* @return the element created.
*/
public DNodeListElement createListElement(NodeMapping self, EObject modelElement, DDiagram diagram) {
final DNodeListElement newNode = DiagramFactory.eINSTANCE.createDNodeListElement();
// getting the right style description : default or conditional
final NodeStyleDescription style = (NodeStyleDescription) new MappingWithInterpreterHelper(interpreter).getBestStyleDescription(self, modelElement, newNode, null, diagram);
newNode.setTarget(modelElement);
newNode.setActualMapping(self);
// semantic elements
DiagramElementMappingHelper.refreshSemanticElements(self, newNode, interpreter);
if (style != null && !StringUtil.isEmpty(style.getLabelExpression())) {
newNode.setName(DiagramElementMappingHelper.computeLabel(newNode, style, diagram, interpreter));
}
/*
* Getting the node size
*/
MappingWithInterpreterHelper.addDoneNode(self, newNode);
final NodeStyle bestStyle = (NodeStyle) new MappingWithInterpreterHelper(interpreter).getBestStyle(self, modelElement, newNode, null, diagram);
if (bestStyle != null) {
newNode.setOwnedStyle(bestStyle);
}
return newNode;
}
/**
* Implementation of {@link NodeMapping#updateListElement(DNodeListElement)} .
*
* @param self
* the node mapping.
* @param listElement
* the view node list element to update.
*/
public void updateListElement(NodeMapping self, DNodeListElement listElement) {
final EObject modelElement = listElement.getTarget();
final DSemanticDecorator container = (DSemanticDecorator) listElement.eContainer();
NodeStyleDescription style = null;
// getting the right style description : default or conditional
DDiagram parentDiagram = listElement.getParentDiagram();
if (container != null) {
style = (NodeStyleDescription) new MappingWithInterpreterHelper(interpreter).getBestStyleDescription(self, modelElement, listElement, container.getTarget(), parentDiagram);
}
if (style != null && !StringUtil.isEmpty(style.getLabelExpression())) {
listElement.setName(DiagramElementMappingHelper.computeLabel(listElement, style, parentDiagram, interpreter));
}
EObject containerVariable = null;
if (listElement.eContainer() instanceof DSemanticDecorator) {
containerVariable = ((DSemanticDecorator) listElement.eContainer()).getTarget();
}
// semantic elements
DiagramElementMappingHelper.refreshSemanticElements(self, listElement, interpreter);
final NodeStyle bestStyle = (NodeStyle) new MappingWithInterpreterHelper(interpreter).getBestStyle(self, modelElement, listElement, containerVariable, parentDiagram);
if ((bestStyle == null || bestStyle.getDescription() != style) && style != null) {
listElement.setOwnedStyle(bestStyle);
}
styleHelper.setAndRefreshStyle(listElement, listElement.getStyle(), bestStyle);
MappingWithInterpreterHelper.addDoneNode(self, listElement);
}
/**
* Implementation of {@link NodeMapping#findDNodeFromEObject(EObject)}.
*
* @param self
* the node mapping.
* @param object
* the semantic element.
* @return the node found.
*/
public static EList<DDiagramElement> findDNodeFromEObject(INodeMappingExt self, EObject object) {
EList result = self.getViewNodesDone().get(object);
if (result == null) {
result = new BasicEList<DDiagramElement>();
}
return result;
}
/**
* Implementation of {@link NodeMapping#addDoneNode(DSemanticDecorator)}.
*
* @param self
* the node mapping.
* @param node
* the node to add.
*/
public static void addDoneNode(INodeMappingExt self, DSemanticDecorator node) {
EList<DSemanticDecorator> list = self.getViewNodesDone().get(node.getTarget());
if (list == null) {
list = new BasicEList<DSemanticDecorator>();
self.getViewNodesDone().put(node.getTarget(), list);
}
list.add(node);
}
/**
* Implementation of {@link NodeMapping#clearDNodesDone()}.
*
* @param self
* the node mapping.
*/
public static void clearDNodesDone(INodeMappingExt self) {
self.getViewNodesDone().clear();
}
/**
* Return <code>true</code> if <code>eObj</code> is an instance of <code>typename</code>.
*
* @param eObj
* an object.
* @param typename
* the name of the type to check.
* @return <code>true</code> if <code>eObj</code> is an instance of <code>typename</code>.
*/
private static boolean isInstanceOf(final EObject eObj, final String typename) {
DslCommonPlugin.PROFILER.startWork(SiriusTasksKey.INSTANCE_OF_KEY);
final boolean result = SiriusPlugin.getDefault().getModelAccessorRegistry().getModelAccessor(eObj).eInstanceOf(eObj, typename);
DslCommonPlugin.PROFILER.stopWork(SiriusTasksKey.INSTANCE_OF_KEY);
return result;
}
}