From c5f505b5630818d4b88750c7c6d40d5f207bbfcc Mon Sep 17 00:00:00 2001 From: Stéphane Bégaudeau Date: Fri, 13 Jan 2017 15:55:33 +0100 Subject: [510028] Move expressions-related code out of the UI plugin Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=510028 Change-Id: I3b1e3724ad8db842d1bb4ca232329af8bc07175c Signed-off-by: Stéphane Bégaudeau --- .../META-INF/MANIFEST.MF | 9 +- .../plugin.properties | 4 +- .../org.eclipse.sirius.properties.core/plugin.xml | 6 + .../properties/core/api/SiriusInputDescriptor.java | 86 +++++ .../properties/core/internal/EditSupportSpec.java | 250 +++++++++++++ .../sirius/properties/core/internal/Messages.java | 3 + .../properties/core/internal/SiriusContext.java | 228 ++++++++++++ .../core/internal/SiriusToolServices.java | 275 ++++++++++++++ .../internal/expressions/DomainClassSwitch.java | 207 +++++++++++ .../PropertiesExpressionQueryProvider.java | 36 ++ .../PropertiesInterpretedExpressionQuery.java | 400 +++++++++++++++++++++ .../core/internal/expressions/VSMNavigation.java | 208 +++++++++++ .../META-INF/MANIFEST.MF | 3 +- .../internal/converters/ConverterTests.java | 2 +- .../META-INF/MANIFEST.MF | 1 - .../plugin.properties | 1 - .../org.eclipse.sirius.ui.properties/plugin.xml | 6 - .../api/AbstractDescriptionConverter.java | 2 +- .../ui/properties/internal/ContributorWrapper.java | 3 +- .../ui/properties/internal/EditSupportSpec.java | 250 ------------- .../sirius/ui/properties/internal/Messages.java | 3 - .../ui/properties/internal/SiriusContext.java | 228 ------------ .../ui/properties/internal/SiriusInputAdapter.java | 3 +- .../properties/internal/SiriusInputDescriptor.java | 85 ----- .../ui/properties/internal/SiriusInterpreter.java | 1 + .../ui/properties/internal/SiriusToolServices.java | 274 -------------- .../internal/expressions/DomainClassSwitch.java | 207 ----------- .../PropertiesExpressionQueryProvider.java | 36 -- .../PropertiesInterpretedExpressionQuery.java | 399 -------------------- .../internal/expressions/VSMNavigation.java | 208 ----------- .../tabprovider/SiriusTabDescriptorProvider.java | 2 +- .../tabprovider/ViewDescriptionConverter.java | 4 +- .../viewpoint/provider/SiriusEditPlugin.java | 7 +- .../org/eclipse/sirius/viewpoint/SiriusPlugin.java | 25 ++ 34 files changed, 1749 insertions(+), 1713 deletions(-) create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/api/SiriusInputDescriptor.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/EditSupportSpec.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusContext.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusToolServices.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/DomainClassSwitch.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesExpressionQueryProvider.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesInterpretedExpressionQuery.java create mode 100644 plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/VSMNavigation.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/EditSupportSpec.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusContext.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputDescriptor.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusToolServices.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/DomainClassSwitch.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesExpressionQueryProvider.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesInterpretedExpressionQuery.java delete mode 100644 plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/VSMNavigation.java diff --git a/plugins/org.eclipse.sirius.properties.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.properties.core/META-INF/MANIFEST.MF index ac232fdb36..1102caf7f5 100644 --- a/plugins/org.eclipse.sirius.properties.core/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.sirius.properties.core/META-INF/MANIFEST.MF @@ -10,13 +10,18 @@ Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.sirius.properties.core.api;version="5.0.0", org.eclipse.sirius.properties.core.api.preferences;version="5.0.0", org.eclipse.sirius.properties.core.internal;version="5.0.0";x-internal:=true, + org.eclipse.sirius.properties.core.internal.expressions;version="5.0.0", org.eclipse.sirius.properties.core.internal.migration;version="5.0.0", org.eclipse.sirius.properties.core.internal.preferences;version="5.0.0";x-internal:=true Require-Bundle: org.eclipse.core.runtime;bundle-version="3.0.0", org.eclipse.sirius;bundle-version="5.0.0", + org.eclipse.sirius.common;bundle-version="5.0.0", org.eclipse.sirius.ecore.extender;bundle-version="5.0.0", - org.eclipse.sirius.properties;bundle-version="5.0.0", org.eclipse.sirius.ext.base;bundle-version="5.0.0", - org.eclipse.eef.common;bundle-version="2.0.0" + org.eclipse.sirius.properties;bundle-version="5.0.0", + org.eclipse.eef.common;bundle-version="2.0.0", + org.eclipse.eef.core;bundle-version="2.0.0", + org.eclipse.emf.transaction;bundle-version="1.8.0", + org.eclipse.sirius.ext.emf.edit;bundle-version="5.0.0" Import-Package: com.google.common.collect;version="[15.0.0,16.0.0)" diff --git a/plugins/org.eclipse.sirius.properties.core/plugin.properties b/plugins/org.eclipse.sirius.properties.core/plugin.properties index 73c72954a8..a775a3ad8f 100644 --- a/plugins/org.eclipse.sirius.properties.core/plugin.properties +++ b/plugins/org.eclipse.sirius.properties.core/plugin.properties @@ -12,4 +12,6 @@ pluginName = Sirius Properties View Runtime providerName = Eclipse Modeling Project -DefaultRulesProvider_DefaultPropertiesNotFound=The model containing the default configuration of the Properties page has not been found. \ No newline at end of file +DefaultRulesProvider_DefaultPropertiesNotFound=The model containing the default configuration of the Properties page has not been found. + +SiriusToolServices_MainTabLabel=Main \ No newline at end of file diff --git a/plugins/org.eclipse.sirius.properties.core/plugin.xml b/plugins/org.eclipse.sirius.properties.core/plugin.xml index 0916f7a3fe..e1ba71b212 100644 --- a/plugins/org.eclipse.sirius.properties.core/plugin.xml +++ b/plugins/org.eclipse.sirius.properties.core/plugin.xml @@ -28,4 +28,10 @@ kind="VSM"> + + + + diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/api/SiriusInputDescriptor.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/api/SiriusInputDescriptor.java new file mode 100644 index 0000000000..646e883cec --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/api/SiriusInputDescriptor.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 Obeo. + * 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.properties.core.api; + +import java.util.Collection; + +import org.eclipse.eef.core.api.InputDescriptor; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.properties.core.internal.SiriusContext; + +import com.google.common.collect.Sets; + +/** + * An EEF InputDescriptor for elements selected in a Sirius context. + * + * @author Pierre-Charles David + */ +public class SiriusInputDescriptor implements InputDescriptor { + /** + * The full context, determined from the original input. + */ + private final SiriusContext context; + + /** + * Creates a SiriusInputDescriptor from the specified input. + * + * @param input + * the original input. + */ + public SiriusInputDescriptor(Object input) { + this.context = SiriusContext.from(input); + } + + @Override + public Object getOriginalSelection() { + return context.getInput(); + } + + @Override + public EObject getSemanticElement() { + Option obj = context.getMainSemanticElement(); + if (obj.some()) { + return obj.get(); + } else { + return null; + } + } + + /** + * Returns all the semantic model element associated with the current + * selection, including secondary associated elements if any. + * + * @return all the semantic model element associated with the current + * selection. + */ + public Collection getAllSemanticElements() { + Collection result = Sets.newLinkedHashSet(); + result.add(getSemanticElement()); + Option> additional = context.getAdditionalSemanticElements(); + if (additional.some()) { + result.addAll(additional.get()); + } + return result; + } + + /** + * Returns the full Sirius context determined from the original input, which + * may include addition Sirius-specific information in addition to what can + * be exposed through the generic {@link InputDescriptor} API. + * + * @return the full Sirius context determined from the original input. + */ + public SiriusContext getFullContext() { + return context; + } + +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/EditSupportSpec.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/EditSupportSpec.java new file mode 100644 index 0000000000..571fa864b0 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/EditSupportSpec.java @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 Obeo. + * 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.properties.core.internal; + +import org.eclipse.eef.common.api.utils.Util; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.emf.edit.EditingDomainServices; +import org.eclipse.sirius.properties.core.api.preferences.SiriusPropertiesCorePreferences; +import org.eclipse.sirius.properties.impl.EditSupportImpl; + +/** + * Contains the actual implementation of the EditSupport EOperations. + * + * @author pcdavid + */ +public class EditSupportSpec extends EditSupportImpl { + + private static final String JAVA_LANG_STRING = "java.lang.String"; //$NON-NLS-1$ + + private static final String INT = "int"; //$NON-NLS-1$ + + private static final String JAVA_LANG_INTEGER = "java.lang.Integer"; //$NON-NLS-1$ + + private static final String DOUBLE = "double"; //$NON-NLS-1$ + + private static final String JAVA_LANG_DOUBLE = "java.lang.Double"; //$NON-NLS-1$ + + private static final String CHAR = "char"; //$NON-NLS-1$ + + private static final String JAVA_LANG_CHARACTER = "java.lang.Character"; //$NON-NLS-1$ + + private static final String SHORT = "short"; //$NON-NLS-1$ + + private static final String JAVA_LANG_SHORT = "java.lang.Short"; //$NON-NLS-1$ + + private static final String LONG = "long"; //$NON-NLS-1$ + + private static final String JAVA_LANG_LONG = "java.lang.Long"; //$NON-NLS-1$ + + private static final String FLOAT = "float"; //$NON-NLS-1$ + + private static final String JAVA_LANG_FLOAT = "java.lang.Float"; //$NON-NLS-1$ + + private static final String JAVA_UTIL_DATE = "java.util.Date"; //$NON-NLS-1$ + + private static final String BOOLEAN = "boolean"; //$NON-NLS-1$ + + private static final String JAVA_LANG_BOOLEAN = "java.lang.Boolean"; //$NON-NLS-1$ + + private final EditingDomainServices editServices = new EditingDomainServices(); + + private final SiriusContext context; + + private final Object self; + + /** + * Creates an instance configured to work on the specified target element as + * implicit "self" for all operations. + * + * @param ctx + * the context + * @param target + * the target element. + */ + public EditSupportSpec(SiriusContext ctx, Object target) { + this.context = ctx; + this.self = target; + } + + /** + * Returns the actual target model element, unwrapping the + * {@link EEFViewCategory} if needed. + * + * @return the actual target model element, or null if self is + * not an {@link EObject}. + */ + private EObject getTargetEObject() { + EObject result = null; + if (self instanceof EObject) { + result = (EObject) self; + } + return result; + } + + @Override + public Object getImage() { + EObject target = getTargetEObject(); + if (target != null) { + return this.editServices.getLabelProviderImage(target); + } else { + return null; + } + } + + @Override + public String getText() { + EObject target = getTargetEObject(); + if (target != null) { + return this.editServices.getLabelProviderText(target); + } else { + return String.valueOf(self); + } + } + + @Override + public Object getText(EStructuralFeature feature) { + EObject target = getTargetEObject(); + if (target != null) { + String result = this.editServices.getPropertyDescriptorDisplayName(target, feature.getName()); + if (Util.isBlank(result)) { + result = this.editServices.getLabelProviderText(feature); + } + if (Util.isBlank(result)) { + result = feature.getName(); + } + return result; + } else { + return ""; //$NON-NLS-1$ + } + } + + @Override + public String getTabName() { + EObject target = getTargetEObject(); + final String result; + if (target != null) { + Option mainSemanticElement = context.getMainSemanticElement(); + if (mainSemanticElement.some() && mainSemanticElement.get().equals(target)) { + result = Messages.SiriusToolServices_MainTabLabel; + } else { + result = this.editServices.getLabelProviderText(target); + } + } else { + result = String.valueOf(target); + } + return elide(result, SiriusPropertiesCorePreferences.INSTANCE.getMaxLengthTabName()); + } + + private String elide(String s, int maxLength) { + final String dots = "..."; //$NON-NLS-1$ + if (dots.length() <= maxLength && maxLength < s.length()) { + return s.substring(0, maxLength - dots.length()) + dots; + } else { + return s; + } + } + + @Override + public EList getChoiceOfValues(EStructuralFeature feature) { + BasicEList result = new BasicEList(); + EObject target = getTargetEObject(); + if (target != null) { + result.addAll(this.editServices.getPropertyDescriptorChoiceOfValues(target, feature.getName())); + } + return result; + + } + + @Override + public boolean isMultiline(EStructuralFeature eStructuralFeature) { + EObject target = getTargetEObject(); + if (target != null) { + return this.editServices.isPropertyDescriptorMultiLine(target, eStructuralFeature.getName()); + } else { + return false; + } + } + + @Override + public String getDescription(EStructuralFeature eStructuralFeature) { + EObject target = getTargetEObject(); + if (target != null) { + return this.editServices.getPropertyDescriptorDescription(target, eStructuralFeature.getName()); + } else { + return ""; //$NON-NLS-1$ + } + } + + @Override + public boolean needsTextWidget(EStructuralFeature eStructuralFeature) { + boolean needsTextWidget = false; + + needsTextWidget = needsTextWidget || JAVA_LANG_STRING.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || INT.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_INTEGER.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || DOUBLE.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_DOUBLE.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || CHAR.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_CHARACTER.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || SHORT.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_SHORT.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || LONG.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_LONG.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || FLOAT.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_LANG_FLOAT.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsTextWidget = needsTextWidget || JAVA_UTIL_DATE.equals(eStructuralFeature.getEType().getInstanceTypeName()); + + return needsTextWidget && !eStructuralFeature.isMany(); + } + + @Override + public boolean needsCheckboxWidget(EStructuralFeature eStructuralFeature) { + boolean needsCheckboxWidget = false; + + needsCheckboxWidget = needsCheckboxWidget || BOOLEAN.equals(eStructuralFeature.getEType().getInstanceTypeName()); + needsCheckboxWidget = needsCheckboxWidget || JAVA_LANG_BOOLEAN.equals(eStructuralFeature.getEType().getInstanceTypeName()); + + return needsCheckboxWidget && !eStructuralFeature.isMany(); + } + + @Override + public EList getEStructuralFeatures() { + EList visibleFeatures = new BasicEList<>(); + for (EStructuralFeature eStructuralFeature : this.getTargetEObject().eClass().getEAllStructuralFeatures()) { + if (!eStructuralFeature.isDerived() && !eStructuralFeature.isTransient() && !(eStructuralFeature instanceof EReference && ((EReference) eStructuralFeature).isContainment())) { + visibleFeatures.add(eStructuralFeature); + } + } + return visibleFeatures; + } + + @Override + public Object setValue(EStructuralFeature feature, Object newValue) { + EObject target = getTargetEObject(); + if (target != null) { + Object finalValue = newValue; + if (feature instanceof EAttribute && newValue instanceof String) { + finalValue = EcoreUtil.createFromString(((EAttribute) feature).getEAttributeType(), (String) newValue); + } + target.eSet(feature, finalValue); + } + return self; + } + +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/Messages.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/Messages.java index abb80d2eee..a701ea856e 100644 --- a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/Messages.java +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/Messages.java @@ -29,6 +29,9 @@ public final class Messages { @TranslatableMessage public static String DefaultRulesProvider_DefaultPropertiesNotFound; + @TranslatableMessage + public static String SiriusToolServices_MainTabLabel; + // CHECKSTYLE:ON private Messages() { diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusContext.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusContext.java new file mode 100644 index 0000000000..d32b8214a6 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusContext.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 Obeo. + * 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.properties.core.internal; + +import java.util.Collection; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.sirius.business.api.query.EObjectQuery; +import org.eclipse.sirius.business.api.session.Session; +import org.eclipse.sirius.business.api.session.SessionManager; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.base.Options; +import org.eclipse.sirius.viewpoint.DRepresentation; +import org.eclipse.sirius.viewpoint.DRepresentationElement; +import org.eclipse.sirius.viewpoint.DSemanticDecorator; + +/** + * Provides contextual information to clients about where a given element exists + * in terms of Sirius elements. Depending on the "input" element this context + * refers to, any of the context fields may be absent. + * + * @author pcdavid + * @since 4.0 + */ +public final class SiriusContext { + /** + * The original element from which the context information was computed. + */ + private Object input; + + /** + * The Sirius Session of which the input is part of, if it could be + * determined unambiguously. + */ + private final Session session; + + /** + * The Sirius representation of which the input is part of, if it could be + * determined unambiguously. + */ + private final DRepresentation representation; + + /** + * The DSemanticDecorator associated witht the input, which only makes sense + * if the input element itself is a DSemanticDecorator. + */ + private final DSemanticDecorator semanticDecorator; + + /** + * The main semantic element associated with the input, if it could be + * determined unambiguously. + */ + private final EObject mainSemanticElement; + + private SiriusContext(Object input, Session session, DRepresentation representation, DSemanticDecorator semanticDecorator, EObject mainSemanticElement) { + this.input = input; + this.session = session; + this.representation = representation; + this.semanticDecorator = semanticDecorator; + this.mainSemanticElement = mainSemanticElement; + } + + /** + * Static factory method. + * + * @param input + * the input element. + * @return the computed context. + */ + public static SiriusContext from(Object input) { + SiriusContext result = new SiriusContext(input, null, null, null, null); + if (input instanceof Session) { + result = fromSession((Session) input); + } else if (input instanceof DRepresentation) { + result = fromDRepresentation((DRepresentation) input); + } else if (input instanceof DRepresentationElement) { + result = fromDRepresentationElement((DRepresentationElement) input); + } else if (input instanceof EObject) { + result = fromUnknownEObject((EObject) input); + } else if (input instanceof IAdaptable) { + Object adapted = ((IAdaptable) input).getAdapter(EObject.class); + if (adapted instanceof EObject) { + result = from(adapted); + // Remember the original unadapted input. + result.input = input; + } + } + return result; + } + + /** + * From a session as a starting point, we can not deduce anything more + * precise. + */ + private static SiriusContext fromSession(Session session) { + return new SiriusContext(session, session, null, null, null); + } + + /** + * From a DRepresentation, we can deduce the containing Session (if we are + * inside an active one). Some representations (in practice, all current + * cases) are also DSemanticDecorator and thus have an associated semantic + * element. + */ + private static SiriusContext fromDRepresentation(DRepresentation repr) { + Session session = new EObjectQuery(repr).getSession(); + DSemanticDecorator decorator = null; + if (repr instanceof DSemanticDecorator) { + decorator = (DSemanticDecorator) repr; + } + EObject mainSemanticElement = null; + if (decorator != null) { + mainSemanticElement = decorator.getTarget(); + } + return new SiriusContext(repr, session, repr, decorator, mainSemanticElement); + } + + /** + * From a DRepresentationElement we can deduce everything, both "up" to the + * enclosing session and "down" to the associated semantic elements. + */ + private static SiriusContext fromDRepresentationElement(DRepresentationElement dre) { + Session session = new EObjectQuery(dre).getSession(); + Option repr = new EObjectQuery(dre).getRepresentation(); + return new SiriusContext(dre, session, repr.get(), dre, dre.getTarget()); + } + + /** + * From an unkown EObject, we van only deduce the session (if it is part of + * one), and maybe the semantic element of the object itself is inside one + * of the session's semantic resources. This should only be called as a last + * resort, if all other specific types of input about which we can know more + * have been exhausted. + */ + private static SiriusContext fromUnknownEObject(EObject obj) { + Session session = SessionManager.INSTANCE.getSession(obj); + // Session.getSemanticResources() only returns non-controlled resources, + // so we need to identify the top-level Resource containing the element. + Resource res = EcoreUtil.getRootContainer(obj).eResource(); + EObject semanticElement = null; + if (session != null && res != null && session.getSemanticResources().contains(res)) { + semanticElement = obj; + } + return new SiriusContext(obj, session, null, null, semanticElement); + } + + /** + * The original input element for which this context was created. + * + * @return the original input element. + */ + public Object getInput() { + return input; + } + + /** + * Returns the session to which the input element is associated. May be + * absent if the input element does not exist in the context of a Sirius + * session. + * + * @return the session to which the input element is associated. + */ + public Option getSession() { + return Options.fromNullable(session); + } + + /** + * Returns the Sirius representation to which the input element is + * associated. May be absent if the input element does not exist in the + * context of a single Sirius representation. Note for that semantic + * elements, even if they are currently represented on only one + * representation in their session, are not considered associated to it. + * + * @return the Sirius representation to which the input element is + * associated. + */ + public Option getDRepresentation() { + return Options.fromNullable(representation); + } + + /** + * Returns the {@link DSemanticDecorator} associated to the input, which is + * only available if the input is itself a {@link DSemanticDecorator}. + * + * @return the {@link DSemanticDecorator} associated to the input. + */ + public DSemanticDecorator getSemanticDecorator() { + return semanticDecorator; + } + + /** + * Returns the main semantic element associated to the input. May be absent. + * + * @return the main semantic element associated to the input. + */ + public Option getMainSemanticElement() { + if (semanticDecorator != null) { + return Options.newSome(semanticDecorator.getTarget()); + } else { + return Options.newSome(mainSemanticElement); + } + } + + /** + * Returns the additional semantic elements associated to the input. May be + * absent. + * + * @return the additional semantic elements associated to the input. + */ + public Option> getAdditionalSemanticElements() { + if (semanticDecorator instanceof DRepresentationElement) { + return Options.newSome((Collection) ((DRepresentationElement) semanticDecorator).getSemanticElements()); + } else { + return Options.newNone(); + } + } +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusToolServices.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusToolServices.java new file mode 100644 index 0000000000..a1b202f3d3 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/SiriusToolServices.java @@ -0,0 +1,275 @@ +/******************************************************************************* + * Copyright (c) 2015, 2017 Obeo. + * 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.properties.core.internal; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.sirius.business.api.helper.task.ICommandTask; +import org.eclipse.sirius.business.api.helper.task.TaskHelper; +import org.eclipse.sirius.business.api.query.EObjectQuery; +import org.eclipse.sirius.business.api.session.Session; +import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.properties.EditSupport; +import org.eclipse.sirius.properties.ViewExtensionDescription; +import org.eclipse.sirius.properties.core.api.DefaultRulesProvider; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; +import org.eclipse.sirius.tools.api.command.SiriusCommand; +import org.eclipse.sirius.viewpoint.DRepresentation; +import org.eclipse.sirius.viewpoint.DSemanticDecorator; +import org.eclipse.sirius.viewpoint.SiriusPlugin; +import org.eclipse.sirius.viewpoint.description.Viewpoint; +import org.eclipse.sirius.viewpoint.description.tool.InitialOperation; +import org.eclipse.sirius.viewpoint.description.tool.ModelOperation; + +/** + * This class contains various services provided by the Sirius UI Properties + * bundle to the interpreter. + * + * @author sbegaudeau + */ +public class SiriusToolServices { + + /** + * Executes the operation with the given URI. + * + * @param self + * the service invocation target. + * @param eObject + * The EObject to use as the operation's context + * @param initialCommandUri + * the URI of the operation to execute + * @return the model element on which the tool was executed. + */ + public EObject executeOperation(SiriusInputDescriptor self, EObject eObject, String initialCommandUri) { + if (!eObject.eIsProxy()) { + Session session = new EObjectQuery(eObject).getSession(); + if (session != null) { + ModelOperation modelOperation = findModelOperation(initialCommandUri, session); + if (modelOperation != null) { + ModelAccessor modelAccessor = session.getModelAccessor(); + ICommandTask task = new TaskHelper(modelAccessor, SiriusPlugin.getDefault().getUiCallback()).buildTaskFromModelOperation(eObject, modelOperation); + SiriusCommand command = new SiriusCommand(session.getTransactionalEditingDomain(), "SiriusToolServices#executeOperation"); //$NON-NLS-1$ + command.getTasks().add(task); + try { + if (command.canExecute()) { + command.execute(); + } + } finally { + command.dispose(); + } + } + } + } + return eObject; + } + + /** + * Resolves the actual {@link ModelOperation} to execute given its URI. + * + * @param initialCommandUri + * the URI of the operation to search for. + * @param session + * the Sirius session which determines the scope to search into. + * @return the {@link ModelOperation} instance found at the specified URI, + * either in one of the VSMs for which at least one Viewpoint is + * currently enabled in the session, or from the default ruleset, or + * null if no matching operation could be located. + */ + private ModelOperation findModelOperation(String initialCommandUri, Session session) { + URI commandResourceURI = URI.createURI(initialCommandUri).trimFragment(); + for (Resource res : getResourcesInScope(session)) { + if (commandResourceURI.equals(res.getURI())) { + EObject modelOperationEObject = res.getEObject(URI.createURI(initialCommandUri).fragment()); + if (modelOperationEObject instanceof InitialOperation) { + return ((InitialOperation) modelOperationEObject).getFirstModelOperations(); + } + } + } + return null; + } + + /** + * Returns all the (VSM-like) resources in which to search for the + * {@link ModelOperation} to execute. + * + * @param session + * the Sirius session. + * @return all the resources in which to look for the ModelOperation, in + * order of preference. + */ + private Set getResourcesInScope(Session session) { + Set result = new LinkedHashSet<>(); + Collection selectedViewpoints = session.getSelectedViewpoints(true); + for (Viewpoint viewpoint : selectedViewpoints) { + Resource eResource = viewpoint.eResource(); + if (eResource != null) { + result.add(eResource); + } + } + ViewExtensionDescription defaults = DefaultRulesProvider.INSTANCE.getDefaultRules(); + if (defaults != null && defaults.eResource() != null) { + result.add(defaults.eResource()); + } + return result; + } + + /** + * Returns the {@link SiriusContext} associated with a + * {@link SiriusInputDescriptor} (typically the "input" variable of the + * properties view). + * + * @param sid + * a {@link SiriusInputDescriptor} (typically the "input" + * variable of the properties view). + * @return the input's full context. + */ + public SiriusContext context(SiriusInputDescriptor sid) { + return sid.getFullContext(); + } + + /** + * Returns the semantic element for the given input descriptor. + * + * @param sid + * The input descriptor + * @return The semantic element for the given input descriptor + */ + public EObject getSemanticElement(SiriusInputDescriptor sid) { + return sid.getSemanticElement(); + } + + /** + * Returns all the semantic elements for the given input descriptor. + * + * @param sid + * The input descriptor + * @return The semantic element for the given input descriptor + */ + public Collection getAllSemanticElements(SiriusInputDescriptor sid) { + return sid.getAllSemanticElements(); + } + + /** + * Returns the original selection for the given input descriptor. + * + * @param sid + * The input descriptor + * @return The original selection for the given input descriptor + */ + public Object getOriginalSelection(SiriusInputDescriptor sid) { + return sid.getOriginalSelection(); + } + + /** + * Returns the Sirius session associated to a given context. + * + * @param ctx + * a Sirius context. + * + * @return the Sirius session associated to a given context. + */ + public Session session(SiriusContext ctx) { + Option s = ctx.getSession(); + if (s.some()) { + return s.get(); + } else { + return null; + } + } + + /** + * Returns the Sirius representation associated to a given context. + * + * @param ctx + * a Sirius context. + * + * @return the Sirius representation associated to a given context. + */ + public DRepresentation representation(SiriusContext ctx) { + Option r = ctx.getDRepresentation(); + if (r.some()) { + return r.get(); + } else { + return null; + } + } + + /** + * Returns the Sirius {@link DSemanticDecorator} associated to a given + * context. + * + * @param ctx + * a Sirius context. + * + * @return the Sirius {@link DSemanticDecorator} associated to a given + * context. + */ + public DSemanticDecorator semanticDecorator(SiriusContext ctx) { + return ctx.getSemanticDecorator(); + } + + /** + * Returns the main semantic element associated to a given context. + * + * @param ctx + * a Sirius context. + * + * @return the main semantic element associated to a given context. + */ + public EObject mainSemanticElement(SiriusContext ctx) { + Option target = ctx.getMainSemanticElement(); + if (target.some()) { + return target.get(); + } else { + return null; + } + } + + /** + * Returns all the semantic elements associated to a given context. + * + * @param ctx + * a Sirius context. + * + * @return all the semantic elements associated to a given context. + */ + public Collection allSemanticElements(SiriusContext ctx) { + Option> elements = ctx.getAdditionalSemanticElements(); + if (elements.some()) { + return elements.get(); + } else { + return null; + } + } + + /** + * Returns a helper with EMF Edit-related operations on a given element. + * + * @param input + * a {@link SiriusInputDescriptor} (typically the "input" + * variable of the properties view). + * @param self + * the target semantic element on which the helper should + * operator. + * @return an instance of EditSupport bounnd to the specified semantic + * element. + */ + public EditSupport emfEditServices(SiriusInputDescriptor input, EObject self) { + EditSupportSpec ess = new EditSupportSpec(input.getFullContext(), self); + return ess; + } +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/DomainClassSwitch.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/DomainClassSwitch.java new file mode 100644 index 0000000000..cb60a45e31 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/DomainClassSwitch.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * 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.properties.core.internal.expressions; + +import java.util.Collection; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.sirius.common.tools.api.interpreter.TypeName; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.base.Options; +import org.eclipse.sirius.properties.CustomExpression; +import org.eclipse.sirius.properties.CustomOperation; +import org.eclipse.sirius.properties.DynamicMappingFor; +import org.eclipse.sirius.properties.DynamicMappingIf; +import org.eclipse.sirius.properties.GroupDescription; +import org.eclipse.sirius.properties.GroupStyle; +import org.eclipse.sirius.properties.OperationDescription; +import org.eclipse.sirius.properties.PageDescription; +import org.eclipse.sirius.properties.PropertiesPackage; +import org.eclipse.sirius.properties.WidgetAction; +import org.eclipse.sirius.properties.WidgetConditionalStyle; +import org.eclipse.sirius.properties.WidgetDescription; +import org.eclipse.sirius.properties.WidgetStyle; +import org.eclipse.sirius.properties.util.PropertiesSwitch; + +import com.google.common.collect.Sets; + +/** + * Computes the domainClass (i.e. expected type of the receiver) for any + * interpreted expression defined on properties views elements. Note that this + * does not handle element inside a properties view description which come from + * other Sirius package (e.g. model operations). + * + * @author pcdavid + */ +public class DomainClassSwitch extends PropertiesSwitch>> { + /** + * Constant used in switches on feature id to consider the case when the + * feature must not be considered. + */ + private static final int DO_NOT_CONSIDER_FEATURE = -1; + + /** + * The feature containing the Interpreted expression. + */ + protected EStructuralFeature feature; + + /** + * Indicates if the feature must be considered. + */ + protected boolean considerFeature; + + /** + * Default constructor. + * + * @param feature + * the feature containing the Interpreted expression + */ + public DomainClassSwitch(EStructuralFeature feature) { + this.feature = feature; + } + + @Override + public Option> doSwitch(EObject theEObject) { + Option> doSwitch = super.doSwitch(theEObject); + if (doSwitch != null) { + return doSwitch; + } + Collection defaultResult = Sets.newLinkedHashSet(); + return Options.newSome(defaultResult); + } + + /** + * Changes the behavior of this switch: if true, then the feature will be + * considered to calculate target types; if false, then the feature will be + * ignored. + * + * @param considerFeature + * true if the feature should be considered, false otherwise + */ + public void setConsiderFeature(boolean considerFeature) { + this.considerFeature = considerFeature; + } + + @Override + public Option> casePageDescription(PageDescription page) { + Option> result = null; + switch (getFeatureId(page.eClass())) { + case PropertiesPackage.PAGE_DESCRIPTION__SEMANTIC_CANDIDATE_EXPRESSION: + /* + * A page can be activated from almost any kind of input: anything + * selectable from any of the representations defined in the same + * VSM can trigger teh evaluation of the page's + * semanticCandidateExpression. Technically we could compute a union + * of all the relevant semantic types, but in practice there is + * little chance that it would be more useful than just EObject. + */ + Collection target = Sets.newLinkedHashSet(); + target.add(TypeName.EOBJECT_TYPENAME.getCompleteName()); + result = Options.newSome(target); + break; + case PropertiesPackage.PAGE_DESCRIPTION__LABEL_EXPRESSION: + case PropertiesPackage.PAGE_DESCRIPTION__PRECONDITION_EXPRESSION: + case DO_NOT_CONSIDER_FEATURE: + result = Options.newSome(VSMNavigation.getPageDomainClass(page)); + break; + default: + break; + } + return result; + } + + @Override + public Option> caseGroupDescription(GroupDescription group) { + Option> result = null; + switch (getFeatureId(group.eClass())) { + case PropertiesPackage.GROUP_DESCRIPTION__SEMANTIC_CANDIDATE_EXPRESSION: + /* + * A Group's semanticCandidateExpression is evaluated from the + * target of its referencing page, which is an instance of the + * page's domainClass. + */ + Collection target = Sets.newLinkedHashSet(); + for (PageDescription page : VSMNavigation.findReferencingPages(group)) { + target.addAll(VSMNavigation.getPageDomainClass(page)); + } + result = Options.newSome(target); + break; + case PropertiesPackage.GROUP_DESCRIPTION__LABEL_EXPRESSION: + case PropertiesPackage.GROUP_DESCRIPTION__PRECONDITION_EXPRESSION: + case DO_NOT_CONSIDER_FEATURE: + result = Options.newSome(VSMNavigation.getGroupDomainClass(group)); + break; + default: + break; + } + return result; + } + + @Override + public Option> caseWidgetDescription(WidgetDescription object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseWidgetStyle(WidgetStyle object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseWidgetConditionalStyle(WidgetConditionalStyle object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseWidgetAction(WidgetAction object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseGroupStyle(GroupStyle object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseCustomExpression(CustomExpression object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseCustomOperation(CustomOperation object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseOperationDescription(OperationDescription object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseDynamicMappingFor(DynamicMappingFor object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + @Override + public Option> caseDynamicMappingIf(DynamicMappingIf object) { + return VSMNavigation.getDomainClassFromContainingGroup(object); + } + + private int getFeatureId(EClass eClass) { + if (considerFeature && feature != null) { + return eClass.getFeatureID(feature); + } else { + return DomainClassSwitch.DO_NOT_CONSIDER_FEATURE; + } + } +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesExpressionQueryProvider.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesExpressionQueryProvider.java new file mode 100644 index 0000000000..0216016943 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesExpressionQueryProvider.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2016, 2017 Obeo. + * 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.properties.core.internal.expressions; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQuery; +import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQueryProvider; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.base.Options; + +/** + * An {@link IInterpretedExpressionQueryProvider} for properties view + * description expressions. + * + * @author pcdavid + */ +public class PropertiesExpressionQueryProvider implements IInterpretedExpressionQueryProvider { + @Override + public Option getExpressionQueryFor(EObject context, EStructuralFeature expressionAttribute) { + if (VSMNavigation.isInsideViewExtensionDescription(context)) { + IInterpretedExpressionQuery value = new PropertiesInterpretedExpressionQuery(context, expressionAttribute); + return Options.newSome(value); + } else { + return Options.newNone(); + } + } +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesInterpretedExpressionQuery.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesInterpretedExpressionQuery.java new file mode 100644 index 0000000000..6922522b37 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/PropertiesInterpretedExpressionQuery.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * 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.properties.core.internal.expressions; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.eef.common.api.utils.Util; +import org.eclipse.eef.core.api.EEFExpressionUtils; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EPackage.Registry; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.sirius.business.api.dialect.description.AbstractInterpretedExpressionQuery; +import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQuery; +import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionTargetSwitch; +import org.eclipse.sirius.business.api.dialect.description.MultiLanguagesValidator; +import org.eclipse.sirius.business.api.query.EObjectQuery; +import org.eclipse.sirius.business.internal.dialect.description.ToolInterpretedExpressionTargetSwitch; +import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext; +import org.eclipse.sirius.common.tools.api.interpreter.TypeName; +import org.eclipse.sirius.common.tools.api.interpreter.ValidationResult; +import org.eclipse.sirius.common.tools.api.interpreter.VariableType; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.base.Options; +import org.eclipse.sirius.properties.DynamicMappingFor; +import org.eclipse.sirius.properties.GroupDescription; +import org.eclipse.sirius.properties.PageDescription; +import org.eclipse.sirius.properties.PropertiesPackage; +import org.eclipse.sirius.properties.ViewExtensionDescription; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; +import org.eclipse.sirius.properties.core.internal.SiriusToolServices; +import org.eclipse.sirius.tools.api.interpreter.context.SiriusInterpreterContextFactory; +import org.eclipse.sirius.viewpoint.ViewpointPackage; +import org.eclipse.sirius.viewpoint.description.DescriptionPackage; +import org.eclipse.sirius.viewpoint.description.Extension; +import org.eclipse.sirius.viewpoint.description.Group; +import org.eclipse.sirius.viewpoint.description.RepresentationDescription; +import org.eclipse.sirius.viewpoint.description.tool.InitialOperation; +import org.eclipse.sirius.viewpoint.description.tool.ToolPackage; +import org.eclipse.sirius.viewpoint.description.validation.ValidationPackage; + +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +/** + * An {@code IInterpretedExpressionQuery} for expressions occuring inside + * properties view descriptions. + * + * @author pcdavid + */ +@SuppressWarnings("restriction") +public final class PropertiesInterpretedExpressionQuery extends AbstractInterpretedExpressionQuery implements IInterpretedExpressionQuery { + private Collection packagesToImport; + + /** + * Constructor. + * + * @param target + * the VSM element on which the expression appears. + * @param expressionAttribute + * the attribute of the VSM element which defines the expression + * (assumed to be an InterpredExpression). + */ + public PropertiesInterpretedExpressionQuery(EObject target, EStructuralFeature expressionAttribute) { + super(target, expressionAttribute); + } + + @Override + protected void initializeTargetSwitch() { + this.targetSwitch = new PropertiesExpressionsGlobalTargetSwitch(feature); + } + + @Override + public Collection getPackagesToImport() { + /* + * We can't rely on the default implementation here, as it assumes we + * are inside a RepresentationDescription, which is not the case for + * properties definitions. + */ + if (packagesToImport == null) { + packagesToImport = PropertiesInterpretedExpressionQuery.getEPackagesInScope(target); + } + return packagesToImport; + } + + @Override + public Collection getDependencies() { + /* + * We can't rely on the default implementation here, as it assumes we + * are inside a Viewpoint, which is not the case for properties + * definitions. + */ + if (dependencies == null) { + Collection result = Lists.newArrayList(VSMNavigation.getJavaExtensionsInVSM(target)); + // Make sure the implicitly registered SiriusToolServices class is + // also visible. + result.add(SiriusToolServices.class.getName()); + dependencies = result; + } + return dependencies; + } + + private static Collection getEPackagesInScope(EObject target) { + Collection result = Sets.newLinkedHashSet(); + + boolean needsGlobalPackages = false; + for (RepresentationDescription desc : VSMNavigation.getRepresentationDescriptionsInVSM(target)) { + EList configured = desc.getMetamodel(); + result.addAll(configured); + if (configured.isEmpty()) { + /* + * If at least one of the possible source representations has no + * explicitly configured metamodel, we must include the globally + * registered packages. + */ + needsGlobalPackages = true; + } + } + + if (needsGlobalPackages) { + result.addAll(PropertiesInterpretedExpressionQuery.getAllRegisteredEPackages(EPackage.Registry.INSTANCE)); + } + + // Also add metamodels explicitly added to the ViewExtensionDescription, + // if any. + Option viewDescriptionOpt = new EObjectQuery(target).getFirstAncestorOfType(PropertiesPackage.Literals.VIEW_EXTENSION_DESCRIPTION); + if (viewDescriptionOpt.some()) { + ViewExtensionDescription ved = (ViewExtensionDescription) viewDescriptionOpt.get(); + result.addAll(ved.getMetamodels()); + } + + // In all cases, we make sure the core Sirius metamodels are present... + result.add(EcorePackage.eINSTANCE); + result.add(ViewpointPackage.eINSTANCE); + result.add(DescriptionPackage.eINSTANCE); + result.add(ToolPackage.eINSTANCE); + result.add(ValidationPackage.eINSTANCE); + // ... and the properties view one too. + result.add(PropertiesPackage.eINSTANCE); + + return result; + } + + private static Collection getAllRegisteredEPackages(Registry source) { + Collection result = Sets.newLinkedHashSet(); + for (String nsURI : Sets.newLinkedHashSet(source.keySet())) { + try { + result.add(source.getEPackage(nsURI)); + // CHECKSTYLE:OFF + } catch (Throwable e) { + /* + * anything might happen here depending on the other Eclipse + * tools, and we've seen many time tools breaking all the + * others. + */ + // CHECKSTYLE:ON + } + } + return result; + } + + @Override + public Map getAvailableVariables() { + if (availableVariables == null) { + availableVariables = Maps.newLinkedHashMap(); + } + + // going through eContainer() to declare any For variable (dynamic + // mappings) + EObject cur = target; + while (!(cur instanceof Group) && cur != null) { + EObject parent = cur.eContainer(); + if (parent instanceof DynamicMappingFor) { + String iteratorName = ((DynamicMappingFor) parent).getIterator(); + if (!Util.isBlank(iteratorName)) { + VariableType iteratorType = getResultType(parent, PropertiesPackage.Literals.DYNAMIC_MAPPING_FOR__ITERABLE_EXPRESSION); + availableVariables.put(iteratorName, iteratorType); + } + } + cur = parent; + } + + if (isFromOrInheritsPropertiesEPackage(this.target)) { + // "input" is always available. + availableVariables.put(EEFExpressionUtils.INPUT, VariableType.fromJavaClass(SiriusInputDescriptor.class)); + + if (feature == PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATE_DISPLAY_EXPRESSION) { + VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATES_EXPRESSION); + availableVariables.put(EEFExpressionUtils.EEFSelect.CANDIDATE, candidatesExpressionType); + } else if (feature == PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATE_DISPLAY_EXPRESSION) { + VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATES_EXPRESSION); + availableVariables.put(EEFExpressionUtils.EEFSelect.CANDIDATE, candidatesExpressionType); + } else if (feature == PropertiesPackage.Literals.LABEL_DESCRIPTION__DISPLAY_EXPRESSION) { + VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.LABEL_DESCRIPTION__VALUE_EXPRESSION); + availableVariables.put(EEFExpressionUtils.EEFReference.VALUE, candidatesExpressionType); + } else if (feature == PropertiesPackage.Literals.LIST_DESCRIPTION__DISPLAY_EXPRESSION) { + VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.LIST_DESCRIPTION__VALUE_EXPRESSION); + availableVariables.put(EEFExpressionUtils.EEFList.VALUE, candidatesExpressionType); + } else if (feature == PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__DISPLAY_EXPRESSION) { + VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__VALUE_EXPRESSION); + availableVariables.put(EEFExpressionUtils.EEFReference.VALUE, candidatesExpressionType); + } else if (feature == PropertiesPackage.Literals.DYNAMIC_MAPPING_IF__PREDICATE_EXPRESSION) { + if (target.eContainer() instanceof DynamicMappingFor) { + DynamicMappingFor forDefinition = (DynamicMappingFor) target.eContainer(); + String iteratorName = forDefinition.getIterator(); + if (!Util.isBlank(iteratorName)) { + VariableType iteratorType = getResultType(forDefinition, PropertiesPackage.Literals.DYNAMIC_MAPPING_FOR__ITERABLE_EXPRESSION); + availableVariables.put(iteratorName, iteratorType); + } + } + } + return availableVariables; + } else { + return super.getAvailableVariables(); + } + } + + /** + * return true if the given EObject is from PropertiesPackage or inherits + * from one of the EClasses of PropertiesPackage. + * + * @param object + * any EObject + * @return true if the given EObject is from PropertiesPackage or inherits + * from one of the EClasses of PropertiesPackage + */ + private boolean isFromOrInheritsPropertiesEPackage(EObject object) { + boolean isPropertiesElement = false; + Iterator it = Iterators.concat(Iterators.singletonIterator(object.eClass()), object.eClass().getEAllSuperTypes().iterator()); + while (!isPropertiesElement && it.hasNext()) { + isPropertiesElement = it.next().getEPackage() == PropertiesPackage.eINSTANCE; + } + return isPropertiesElement; + } + + @Override + protected Option getToolContext() { + Option result = super.getToolContext(); + if (!result.some()) { + if (target instanceof PageDescription || target instanceof GroupDescription) { + result = Options.newSome(target); + } else { + result = new EObjectQuery(target).getFirstAncestorOfType(ToolPackage.Literals.INITIAL_OPERATION); + } + } + return result; + } + + @Override + protected void addVariablesFromToolContext(EObject toolContext) { + super.addVariablesFromToolContext(toolContext); + availableVariables.put(EEFExpressionUtils.INPUT, VariableType.fromJavaClass(SiriusInputDescriptor.class)); + if (toolContext instanceof InitialOperation) { + EReference callbackFeature = toolContext.eContainmentFeature(); + VariableType stringType = VariableType.fromString("java.lang.String"); //$NON-NLS-1$ + VariableType booleanType = VariableType.fromString("java.lang.Boolean"); //$NON-NLS-1$ + VariableType unkownType = VariableType.fromString(TypeName.EOBJECT_TYPENAME.getCompleteName()); + if (callbackFeature == PropertiesPackage.Literals.TEXT_DESCRIPTION__INITIAL_OPERATION) { + availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, stringType); + } else if (callbackFeature == PropertiesPackage.Literals.CHECKBOX_DESCRIPTION__INITIAL_OPERATION) { + availableVariables.put(EEFExpressionUtils.EEFCheckbox.NEW_VALUE, booleanType); + } else if (callbackFeature == PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__INITIAL_OPERATION) { + Option> domainClass = VSMNavigation.getDomainClassFromContainingGroup(toolContext); + if (domainClass.some()) { + availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, VariableType.fromStrings(domainClass.get())); + } else { + availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, unkownType); + } + } else if (callbackFeature == PropertiesPackage.Literals.RADIO_DESCRIPTION__INITIAL_OPERATION) { + /* + * in the case of the radio button the type of newValue is the + * return type of the candidate expression. + */ + availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, getResultType(toolContext.eContainer(), PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATES_EXPRESSION)); + } else if (callbackFeature == PropertiesPackage.Literals.WIDGET_ACTION__INITIAL_OPERATION) { + Option> domainClass = VSMNavigation.getDomainClassFromContainingGroup(toolContext); + if (!domainClass.some()) { + availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, VariableType.fromStrings(domainClass.get())); + } else { + availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, unkownType); + } + } else if (callbackFeature == PropertiesPackage.Literals.SELECT_DESCRIPTION__INITIAL_OPERATION) { + availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, getResultType(toolContext.eContainer(), PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATES_EXPRESSION)); + } + } + } + + private VariableType getResultType(EObject owner, EAttribute attr) { + IInterpreterContext context = SiriusInterpreterContextFactory.createInterpreterContext(owner, attr); + ValidationResult res = MultiLanguagesValidator.getInstance().validateExpression(context, (String) owner.eGet(attr)); + return res.getReturnTypes(); + } + + /** + * The switch used to compute domainClasses for expressions used in + * properties definitions. + * + * @author pcdavid + */ + private static class PropertiesExpressionsGlobalTargetSwitch implements IInterpretedExpressionTargetSwitch { + /** + * The switch for properties-specific expressions. + */ + private final DomainClassSwitch propertiesSwitch; + + /** + * The switch we delegate to for Model Operations. + */ + private final ToolInterpretedExpressionTargetSwitch delegateSwitch; + + /** + * By default ToolInterpretedExpressionTargetSwitch assumes operations + * will appear inside representations or mappings, so we override + * getFirstContextChangingContainer() to locate the parent + * GroupDescription instead. + */ + private static class CustomToolInterpretedExpressionTargetSwitch extends ToolInterpretedExpressionTargetSwitch { + public CustomToolInterpretedExpressionTargetSwitch(EStructuralFeature feature, IInterpretedExpressionTargetSwitch defaultSwitch) { + super(feature, defaultSwitch); + } + + @Override + protected EObject getFirstContextChangingContainer(EObject element) { + EObject defaultResult = super.getFirstContextChangingContainer(element); + if (defaultResult instanceof Extension) { + /* + * The generic algorithm in the super-class does not know + * anything about the properties metamodel but will stop at + * the top-level ViewExtensionDescription as it is an + * Extension. + */ + return VSMNavigation.findClosestGroupDescription(element); + } else { + return defaultResult; + } + } + } + + public PropertiesExpressionsGlobalTargetSwitch(EStructuralFeature feature) { + this.propertiesSwitch = new DomainClassSwitch(feature); + this.delegateSwitch = new CustomToolInterpretedExpressionTargetSwitch(feature, this); + } + + @Override + public Option> doSwitch(EObject target, boolean considerFeature) { + Collection targetTypes = Sets.newLinkedHashSet(); + Option> expressionTarget = Options.newSome(targetTypes); + if (target != null) { + if (expressionTarget.some() && expressionTarget.get().isEmpty()) { + propertiesSwitch.setConsiderFeature(considerFeature); + expressionTarget = propertiesSwitch.doSwitch(target); + } + if (expressionTarget.some() && expressionTarget.get().isEmpty()) { + delegateSwitch.setConsiderFeature(considerFeature); + expressionTarget = delegateSwitch.doSwitch(target); + } + } + return expressionTarget; + } + + @Override + public EObject getFirstRelevantContainer(EObject obj) { + if (obj != null) { + EObject container = obj.eContainer(); + while (container != null && !isRelevant(container)) { + container = container.eContainer(); + } + return container; + } else { + return null; + } + } + + /** + * In this context, relevant containers are top-level pages and groups + * only. The root ViewExtensionDescriptions do not define anything + * relevant for domain class computation. + */ + private boolean isRelevant(EObject container) { + return container instanceof PageDescription || container instanceof GroupDescription; + } + } +} diff --git a/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/VSMNavigation.java b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/VSMNavigation.java new file mode 100644 index 0000000000..230b8ec1a5 --- /dev/null +++ b/plugins/org.eclipse.sirius.properties.core/src/org/eclipse/sirius/properties/core/internal/expressions/VSMNavigation.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * 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.properties.core.internal.expressions; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.eef.common.api.utils.Util; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.sirius.business.api.query.EObjectQuery; +import org.eclipse.sirius.common.tools.api.interpreter.TypeName; +import org.eclipse.sirius.common.tools.api.util.StringUtil; +import org.eclipse.sirius.ext.base.Option; +import org.eclipse.sirius.ext.base.Options; +import org.eclipse.sirius.properties.GroupDescription; +import org.eclipse.sirius.properties.PageDescription; +import org.eclipse.sirius.properties.PropertiesPackage; +import org.eclipse.sirius.properties.ViewExtensionDescription; +import org.eclipse.sirius.viewpoint.description.DescriptionPackage; +import org.eclipse.sirius.viewpoint.description.Group; +import org.eclipse.sirius.viewpoint.description.JavaExtension; +import org.eclipse.sirius.viewpoint.description.RepresentationDescription; +import org.eclipse.sirius.viewpoint.description.Viewpoint; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +/** + * Utility methods to navigate inside a VSM, especially wrt properties + * descriptions. + * + * @author pcdavid + */ +public final class VSMNavigation { + private VSMNavigation() { + // Preven instanciation. + } + + /** + * Tests whether a model element is part of a Sirius properties view + * description. + * + * @param vsmElement + * the element to test. + * @return true if the element is part of a Sirius properties + * view description. + */ + public static boolean isInsideViewExtensionDescription(EObject vsmElement) { + return new EObjectQuery(vsmElement).getFirstAncestorOfType(PropertiesPackage.Literals.VIEW_EXTENSION_DESCRIPTION).some(); + } + + /** + * Returns the domain class of a given {@link PageDescription}, defaulting + * to a generic catch-all type if no value was set explicitly. + * + * @param page + * a {@link PageDescription}. + * @return the names of potential domain classes for that page. + */ + public static Collection getPageDomainClass(PageDescription page) { + if (page != null && !Util.isBlank(page.getDomainClass())) { + return Collections.singleton(page.getDomainClass()); + } else { + return Collections.singleton(TypeName.EOBJECT_TYPENAME.getCompleteName()); + } + } + + /** + * Returns the domain class of a given {@link GroupDescription}, defaulting + * to the union of all the possible domain classes from pages which + * reference that group if no value was set explicitly. + * + * @param group + * a {@link GroupDescription}. + * @return the names of potential domain classes for that group. + */ + public static Collection getGroupDomainClass(GroupDescription group) { + if (group != null && !Util.isBlank(group.getDomainClass())) { + return Collections.singleton(group.getDomainClass()); + } else { + Collection result = Sets.newLinkedHashSet(); + for (PageDescription page : VSMNavigation.findReferencingPages(group)) { + result.addAll(getPageDomainClass(page)); + } + return result; + } + } + + /** + * Returns the domain class of a VSM element from inside a + * {@link GroupDescription} (for example a widget). + * + * @param vsmElement + * the VSM element. + * @return the domain class of the VSM element, as determined by the + * enclosing {@link GroupDescription}. + */ + public static Option> getDomainClassFromContainingGroup(EObject vsmElement) { + Option> result = Options.newNone(); + GroupDescription group = VSMNavigation.findClosestGroupDescription(vsmElement); + if (group != null) { + result = Options.newSome(getGroupDomainClass(group)); + } + return result; + } + + /** + * Get all the representation description defined in the same VSM as a given + * element. + * + * @param vsmElement + * a VSM element. + * @return all the representation description defined in the same VSM. + */ + public static Collection getRepresentationDescriptionsInVSM(EObject vsmElement) { + Collection result = Lists.newArrayList(); + Option answer = getVSMRoot(vsmElement); + if (answer.some()) { + Group group = (Group) answer.get(); + for (Viewpoint viewpoint : group.getOwnedViewpoints()) { + result.addAll(viewpoint.getOwnedRepresentations()); + } + } + return result; + } + + /** + * Finds all the Java extensions registered in the VSM of the specified + * element. + * + * @param vsmElement + * an element from a VSM model. + * @return the qualified names of all the Java extensions registered in the + * same VSM. + */ + public static Collection getJavaExtensionsInVSM(EObject vsmElement) { + Collection result = Lists.newArrayList(); + Option answer = getVSMRoot(vsmElement); + if (answer.some()) { + Group group = (Group) answer.get(); + for (Viewpoint vp : group.getOwnedViewpoints()) { + for (JavaExtension dep : vp.getOwnedJavaExtensions()) { + if (!StringUtil.isEmpty(dep.getQualifiedClassName())) { + result.add(dep.getQualifiedClassName()); + } + } + } + } + return result; + } + + private static Option getVSMRoot(EObject vsmElement) { + return new EObjectQuery(vsmElement).getFirstAncestorOfType(DescriptionPackage.Literals.GROUP); + } + + /** + * Find which pages reference a given group in a VSM. Groups are not + * contained insides pages, but referenced from pages defined inside the + * same {@link ViewExtensionDescription}. + * + * @param group + * a group. + * @return all the pages inside the same ViewExtensionDescription as the + * group that reference it. + */ + public static Set findReferencingPages(GroupDescription group) { + EObject container = group.eContainer(); + if (container instanceof ViewExtensionDescription) { + ViewExtensionDescription ved = (ViewExtensionDescription) container; + Set result = Sets.newLinkedHashSet(); + for (PageDescription page : ved.getPages()) { + if (page.getGroups().contains(group)) { + result.add(page); + } + } + return result; + } else { + return Collections.emptySet(); + } + } + + /** + * Returns the {@link GroupDescription} enclosing a given VSM element, if + * any. + * + * @param vsmElement + * a VSM element. + * @return the {@link GroupDescription} enclosing the element, or + * null if none could be found. + */ + public static GroupDescription findClosestGroupDescription(EObject vsmElement) { + if (vsmElement instanceof GroupDescription) { + return (GroupDescription) vsmElement; + } else { + Option answer = new EObjectQuery(vsmElement).getFirstAncestorOfType(PropertiesPackage.Literals.GROUP_DESCRIPTION); + return answer.some() ? (GroupDescription) answer.get() : null; + } + } +} diff --git a/plugins/org.eclipse.sirius.tests.ui.properties/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.tests.ui.properties/META-INF/MANIFEST.MF index 2955b5d6f1..f809b6ffd5 100644 --- a/plugins/org.eclipse.sirius.tests.ui.properties/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.sirius.tests.ui.properties/META-INF/MANIFEST.MF @@ -17,5 +17,6 @@ Require-Bundle: org.eclipse.sirius.ui.properties;bundle-version="4.1.0", org.eclipse.emf.compare, com.google.guava;bundle-version="[11.0.2,16.0)", org.eclipse.sirius.common.acceleo.aql, - org.eclipse.sirius.common + org.eclipse.sirius.common, + org.eclipse.sirius.properties.core Bundle-Localization: plugin diff --git a/plugins/org.eclipse.sirius.tests.ui.properties/src/org/eclipse/sirius/tests/ui/properties/internal/converters/ConverterTests.java b/plugins/org.eclipse.sirius.tests.ui.properties/src/org/eclipse/sirius/tests/ui/properties/internal/converters/ConverterTests.java index 97e2285a5c..7d8dd94cde 100644 --- a/plugins/org.eclipse.sirius.tests.ui.properties/src/org/eclipse/sirius/tests/ui/properties/internal/converters/ConverterTests.java +++ b/plugins/org.eclipse.sirius.tests.ui.properties/src/org/eclipse/sirius/tests/ui/properties/internal/converters/ConverterTests.java @@ -39,7 +39,7 @@ import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import org.eclipse.sirius.properties.PropertiesPackage; import org.eclipse.sirius.properties.ViewExtensionDescription; -import org.eclipse.sirius.ui.properties.internal.SiriusInputDescriptor; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; import org.eclipse.sirius.ui.properties.internal.tabprovider.ViewDescriptionConverter; import org.junit.Test; diff --git a/plugins/org.eclipse.sirius.ui.properties/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.ui.properties/META-INF/MANIFEST.MF index adc80bf3e3..25a6d8db86 100644 --- a/plugins/org.eclipse.sirius.ui.properties/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.sirius.ui.properties/META-INF/MANIFEST.MF @@ -41,7 +41,6 @@ Bundle-ActivationPolicy: lazy Bundle-Localization: plugin Export-Package: org.eclipse.sirius.ui.properties.api;version="4.1.0", org.eclipse.sirius.ui.properties.internal;version="4.1.0";x-internal:=true, - org.eclipse.sirius.ui.properties.internal.expressions;version="4.1.0";x-internal:=true, org.eclipse.sirius.ui.properties.internal.tabprovider;version="4.1.0";x-internal:=true, org.eclipse.sirius.ui.properties.internal.filter;version="4.1.0";x-internal:=true, org.eclipse.sirius.ui.properties.internal.preferences;version="4.1.0";x-internal:=true diff --git a/plugins/org.eclipse.sirius.ui.properties/plugin.properties b/plugins/org.eclipse.sirius.ui.properties/plugin.properties index 7992440d7f..3a35d3b776 100644 --- a/plugins/org.eclipse.sirius.ui.properties/plugin.properties +++ b/plugins/org.eclipse.sirius.ui.properties/plugin.properties @@ -28,7 +28,6 @@ TransactionalEditingDomainContextAdapter_errorDuringCommand = Errors occured dur siriusTabDescriptorFilter.Label=Sirius EEF Tab Descriptor Filter siriusTabDescriptorFilter.Description=Filters the properties tabs according to a precondition SiriusToolServices_DefaultCategoryName=Default -SiriusToolServices_MainTabLabel=Main # Preferences preference.page.title.org.eclipse.sirius.ui.properties.general=Sirius Properties View diff --git a/plugins/org.eclipse.sirius.ui.properties/plugin.xml b/plugins/org.eclipse.sirius.ui.properties/plugin.xml index 026b9e2304..7bce947235 100644 --- a/plugins/org.eclipse.sirius.ui.properties/plugin.xml +++ b/plugins/org.eclipse.sirius.ui.properties/plugin.xml @@ -63,12 +63,6 @@ contributorId="org.eclipse.sirius.ui.tools.views.model.explorer"> - - - - null if self is - * not an {@link EObject}. - */ - private EObject getTargetEObject() { - EObject result = null; - if (self instanceof EObject) { - result = (EObject) self; - } - return result; - } - - @Override - public Object getImage() { - EObject target = getTargetEObject(); - if (target != null) { - return this.editServices.getLabelProviderImage(target); - } else { - return null; - } - } - - @Override - public String getText() { - EObject target = getTargetEObject(); - if (target != null) { - return this.editServices.getLabelProviderText(target); - } else { - return String.valueOf(self); - } - } - - @Override - public Object getText(EStructuralFeature feature) { - EObject target = getTargetEObject(); - if (target != null) { - String result = this.editServices.getPropertyDescriptorDisplayName(target, feature.getName()); - if (Util.isBlank(result)) { - result = this.editServices.getLabelProviderText(feature); - } - if (Util.isBlank(result)) { - result = feature.getName(); - } - return result; - } else { - return ""; //$NON-NLS-1$ - } - } - - @Override - public String getTabName() { - EObject target = getTargetEObject(); - final String result; - if (target != null) { - Option mainSemanticElement = context.getMainSemanticElement(); - if (mainSemanticElement.some() && mainSemanticElement.get().equals(target)) { - result = Messages.SiriusToolServices_MainTabLabel; - } else { - result = this.editServices.getLabelProviderText(target); - } - } else { - result = String.valueOf(target); - } - return elide(result, SiriusPropertiesCorePreferences.INSTANCE.getMaxLengthTabName()); - } - - private String elide(String s, int maxLength) { - final String dots = "..."; //$NON-NLS-1$ - if (dots.length() <= maxLength && maxLength < s.length()) { - return s.substring(0, maxLength - dots.length()) + dots; - } else { - return s; - } - } - - @Override - public EList getChoiceOfValues(EStructuralFeature feature) { - BasicEList result = new BasicEList(); - EObject target = getTargetEObject(); - if (target != null) { - result.addAll(this.editServices.getPropertyDescriptorChoiceOfValues(target, feature.getName())); - } - return result; - - } - - @Override - public boolean isMultiline(EStructuralFeature eStructuralFeature) { - EObject target = getTargetEObject(); - if (target != null) { - return this.editServices.isPropertyDescriptorMultiLine(target, eStructuralFeature.getName()); - } else { - return false; - } - } - - @Override - public String getDescription(EStructuralFeature eStructuralFeature) { - EObject target = getTargetEObject(); - if (target != null) { - return this.editServices.getPropertyDescriptorDescription(target, eStructuralFeature.getName()); - } else { - return ""; //$NON-NLS-1$ - } - } - - @Override - public boolean needsTextWidget(EStructuralFeature eStructuralFeature) { - boolean needsTextWidget = false; - - needsTextWidget = needsTextWidget || JAVA_LANG_STRING.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || INT.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_INTEGER.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || DOUBLE.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_DOUBLE.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || CHAR.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_CHARACTER.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || SHORT.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_SHORT.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || LONG.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_LONG.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || FLOAT.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_LANG_FLOAT.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsTextWidget = needsTextWidget || JAVA_UTIL_DATE.equals(eStructuralFeature.getEType().getInstanceTypeName()); - - return needsTextWidget && !eStructuralFeature.isMany(); - } - - @Override - public boolean needsCheckboxWidget(EStructuralFeature eStructuralFeature) { - boolean needsCheckboxWidget = false; - - needsCheckboxWidget = needsCheckboxWidget || BOOLEAN.equals(eStructuralFeature.getEType().getInstanceTypeName()); - needsCheckboxWidget = needsCheckboxWidget || JAVA_LANG_BOOLEAN.equals(eStructuralFeature.getEType().getInstanceTypeName()); - - return needsCheckboxWidget && !eStructuralFeature.isMany(); - } - - @Override - public EList getEStructuralFeatures() { - EList visibleFeatures = new BasicEList<>(); - for (EStructuralFeature eStructuralFeature : this.getTargetEObject().eClass().getEAllStructuralFeatures()) { - if (!eStructuralFeature.isDerived() && !eStructuralFeature.isTransient() && !(eStructuralFeature instanceof EReference && ((EReference) eStructuralFeature).isContainment())) { - visibleFeatures.add(eStructuralFeature); - } - } - return visibleFeatures; - } - - @Override - public Object setValue(EStructuralFeature feature, Object newValue) { - EObject target = getTargetEObject(); - if (target != null) { - Object finalValue = newValue; - if (feature instanceof EAttribute && newValue instanceof String) { - finalValue = EcoreUtil.createFromString(((EAttribute) feature).getEAttributeType(), (String) newValue); - } - target.eSet(feature, finalValue); - } - return self; - } - -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/Messages.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/Messages.java index 105ed81c9d..37b6349c9d 100644 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/Messages.java +++ b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/Messages.java @@ -40,9 +40,6 @@ public final class Messages { @TranslatableMessage public static String SiriusToolServices_DefaultCategoryName; - @TranslatableMessage - public static String SiriusToolServices_MainTabLabel; - @TranslatableMessage public static String TransactionalEditingDomainContextAdapter_errorDuringCommand; diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusContext.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusContext.java deleted file mode 100644 index e78f880a48..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusContext.java +++ /dev/null @@ -1,228 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal; - -import java.util.Collection; - -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.sirius.business.api.query.EObjectQuery; -import org.eclipse.sirius.business.api.session.Session; -import org.eclipse.sirius.business.api.session.SessionManager; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.ext.base.Options; -import org.eclipse.sirius.viewpoint.DRepresentation; -import org.eclipse.sirius.viewpoint.DRepresentationElement; -import org.eclipse.sirius.viewpoint.DSemanticDecorator; - -/** - * Provides contextual information to clients about where a given element exists - * in terms of Sirius elements. Depending on the "input" element this context - * refers to, any of the context fields may be absent. - * - * @author pcdavid - * @since 4.0 - */ -public final class SiriusContext { - /** - * The original element from which the context information was computed. - */ - private Object input; - - /** - * The Sirius Session of which the input is part of, if it could be - * determined unambiguously. - */ - private final Session session; - - /** - * The Sirius representation of which the input is part of, if it could be - * determined unambiguously. - */ - private final DRepresentation representation; - - /** - * The DSemanticDecorator associated witht the input, which only makes sense - * if the input element itself is a DSemanticDecorator. - */ - private final DSemanticDecorator semanticDecorator; - - /** - * The main semantic element associated with the input, if it could be - * determined unambiguously. - */ - private final EObject mainSemanticElement; - - private SiriusContext(Object input, Session session, DRepresentation representation, DSemanticDecorator semanticDecorator, EObject mainSemanticElement) { - this.input = input; - this.session = session; - this.representation = representation; - this.semanticDecorator = semanticDecorator; - this.mainSemanticElement = mainSemanticElement; - } - - /** - * Static factory method. - * - * @param input - * the input element. - * @return the computed context. - */ - public static SiriusContext from(Object input) { - SiriusContext result = new SiriusContext(input, null, null, null, null); - if (input instanceof Session) { - result = fromSession((Session) input); - } else if (input instanceof DRepresentation) { - result = fromDRepresentation((DRepresentation) input); - } else if (input instanceof DRepresentationElement) { - result = fromDRepresentationElement((DRepresentationElement) input); - } else if (input instanceof EObject) { - result = fromUnknownEObject((EObject) input); - } else if (input instanceof IAdaptable) { - Object adapted = ((IAdaptable) input).getAdapter(EObject.class); - if (adapted instanceof EObject) { - result = from(adapted); - // Remember the original unadapted input. - result.input = input; - } - } - return result; - } - - /** - * From a session as a starting point, we can not deduce anything more - * precise. - */ - private static SiriusContext fromSession(Session session) { - return new SiriusContext(session, session, null, null, null); - } - - /** - * From a DRepresentation, we can deduce the containing Session (if we are - * inside an active one). Some representations (in practice, all current - * cases) are also DSemanticDecorator and thus have an associated semantic - * element. - */ - private static SiriusContext fromDRepresentation(DRepresentation repr) { - Session session = new EObjectQuery(repr).getSession(); - DSemanticDecorator decorator = null; - if (repr instanceof DSemanticDecorator) { - decorator = (DSemanticDecorator) repr; - } - EObject mainSemanticElement = null; - if (decorator != null) { - mainSemanticElement = decorator.getTarget(); - } - return new SiriusContext(repr, session, repr, decorator, mainSemanticElement); - } - - /** - * From a DRepresentationElement we can deduce everything, both "up" to the - * enclosing session and "down" to the associated semantic elements. - */ - private static SiriusContext fromDRepresentationElement(DRepresentationElement dre) { - Session session = new EObjectQuery(dre).getSession(); - Option repr = new EObjectQuery(dre).getRepresentation(); - return new SiriusContext(dre, session, repr.get(), dre, dre.getTarget()); - } - - /** - * From an unkown EObject, we van only deduce the session (if it is part of - * one), and maybe the semantic element of the object itself is inside one - * of the session's semantic resources. This should only be called as a last - * resort, if all other specific types of input about which we can know more - * have been exhausted. - */ - private static SiriusContext fromUnknownEObject(EObject obj) { - Session session = SessionManager.INSTANCE.getSession(obj); - // Session.getSemanticResources() only returns non-controlled resources, - // so we need to identify the top-level Resource containing the element. - Resource res = EcoreUtil.getRootContainer(obj).eResource(); - EObject semanticElement = null; - if (session != null && res != null && session.getSemanticResources().contains(res)) { - semanticElement = obj; - } - return new SiriusContext(obj, session, null, null, semanticElement); - } - - /** - * The original input element for which this context was created. - * - * @return the original input element. - */ - public Object getInput() { - return input; - } - - /** - * Returns the session to which the input element is associated. May be - * absent if the input element does not exist in the context of a Sirius - * session. - * - * @return the session to which the input element is associated. - */ - public Option getSession() { - return Options.fromNullable(session); - } - - /** - * Returns the Sirius representation to which the input element is - * associated. May be absent if the input element does not exist in the - * context of a single Sirius representation. Note for that semantic - * elements, even if they are currently represented on only one - * representation in their session, are not considered associated to it. - * - * @return the Sirius representation to which the input element is - * associated. - */ - public Option getDRepresentation() { - return Options.fromNullable(representation); - } - - /** - * Returns the {@link DSemanticDecorator} associated to the input, which is - * only available if the input is itself a {@link DSemanticDecorator}. - * - * @return the {@link DSemanticDecorator} associated to the input. - */ - public DSemanticDecorator getSemanticDecorator() { - return semanticDecorator; - } - - /** - * Returns the main semantic element associated to the input. May be absent. - * - * @return the main semantic element associated to the input. - */ - public Option getMainSemanticElement() { - if (semanticDecorator != null) { - return Options.newSome(semanticDecorator.getTarget()); - } else { - return Options.newSome(mainSemanticElement); - } - } - - /** - * Returns the additional semantic elements associated to the input. May be - * absent. - * - * @return the additional semantic elements associated to the input. - */ - public Option> getAdditionalSemanticElements() { - if (semanticDecorator instanceof DRepresentationElement) { - return Options.newSome((Collection) ((DRepresentationElement) semanticDecorator).getSemanticElements()); - } else { - return Options.newNone(); - } - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputAdapter.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputAdapter.java index 5761f99c20..b627ae5933 100644 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputAdapter.java +++ b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Obeo. + * Copyright (c) 2016, 2017 Obeo. * 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 @@ -12,6 +12,7 @@ package org.eclipse.sirius.ui.properties.internal; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.eef.core.api.InputDescriptor; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; /** * An adapter factory to convert an element selected in Sirius into a suitable diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputDescriptor.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputDescriptor.java deleted file mode 100644 index 9bceec0859..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInputDescriptor.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal; - -import java.util.Collection; - -import org.eclipse.eef.core.api.InputDescriptor; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.sirius.ext.base.Option; - -import com.google.common.collect.Sets; - -/** - * An EEF InputDescriptor for elements selected in a Sirius context. - * - * @author Pierre-Charles David - */ -public class SiriusInputDescriptor implements InputDescriptor { - /** - * The full context, determined from the original input. - */ - private final SiriusContext context; - - /** - * Creates a SiriusInputDescriptor from the specified input. - * - * @param input - * the original input. - */ - public SiriusInputDescriptor(Object input) { - this.context = SiriusContext.from(input); - } - - @Override - public Object getOriginalSelection() { - return context.getInput(); - } - - @Override - public EObject getSemanticElement() { - Option obj = context.getMainSemanticElement(); - if (obj.some()) { - return obj.get(); - } else { - return null; - } - } - - /** - * Returns all the semantic model element associated with the current - * selection, including secondary associated elements if any. - * - * @return all the semantic model element associated with the current - * selection. - */ - public Collection getAllSemanticElements() { - Collection result = Sets.newLinkedHashSet(); - result.add(getSemanticElement()); - Option> additional = context.getAdditionalSemanticElements(); - if (additional.some()) { - result.addAll(additional.get()); - } - return result; - } - - /** - * Returns the full Sirius context determined from the original input, which - * may include addition Sirius-specific information in addition to what can - * be exposed through the generic {@link InputDescriptor} API. - * - * @return the full Sirius context determined from the original input. - */ - public SiriusContext getFullContext() { - return context; - } - -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInterpreter.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInterpreter.java index 8ef9cd2dcd..5e0474676b 100644 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInterpreter.java +++ b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusInterpreter.java @@ -22,6 +22,7 @@ import org.eclipse.sirius.common.interpreter.api.IEvaluationResult; import org.eclipse.sirius.common.interpreter.api.IInterpreter; import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException; import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterWithDiagnostic; +import org.eclipse.sirius.properties.core.internal.SiriusToolServices; import com.google.common.base.Preconditions; diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusToolServices.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusToolServices.java deleted file mode 100644 index 28e124c7b0..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/SiriusToolServices.java +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 Obeo. - * 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.ui.properties.internal; - -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.sirius.business.api.helper.task.ICommandTask; -import org.eclipse.sirius.business.api.helper.task.TaskHelper; -import org.eclipse.sirius.business.api.query.EObjectQuery; -import org.eclipse.sirius.business.api.session.Session; -import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.properties.EditSupport; -import org.eclipse.sirius.properties.ViewExtensionDescription; -import org.eclipse.sirius.properties.core.api.DefaultRulesProvider; -import org.eclipse.sirius.tools.api.command.SiriusCommand; -import org.eclipse.sirius.viewpoint.DRepresentation; -import org.eclipse.sirius.viewpoint.DSemanticDecorator; -import org.eclipse.sirius.viewpoint.description.Viewpoint; -import org.eclipse.sirius.viewpoint.description.tool.InitialOperation; -import org.eclipse.sirius.viewpoint.description.tool.ModelOperation; -import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin; - -/** - * This class contains various services provided by the Sirius UI Properties - * bundle to the interpreter. - * - * @author sbegaudeau - */ -public class SiriusToolServices { - - /** - * Executes the operation with the given URI. - * - * @param self - * the service invocation target. - * @param eObject - * The EObject to use as the operation's context - * @param initialCommandUri - * the URI of the operation to execute - * @return the model element on which the tool was executed. - */ - public EObject executeOperation(SiriusInputDescriptor self, EObject eObject, String initialCommandUri) { - if (!eObject.eIsProxy()) { - Session session = new EObjectQuery(eObject).getSession(); - if (session != null) { - ModelOperation modelOperation = findModelOperation(initialCommandUri, session); - if (modelOperation != null) { - ModelAccessor modelAccessor = session.getModelAccessor(); - ICommandTask task = new TaskHelper(modelAccessor, SiriusEditPlugin.getPlugin().getUiCallback()).buildTaskFromModelOperation(eObject, modelOperation); - SiriusCommand command = new SiriusCommand(session.getTransactionalEditingDomain(), "SiriusToolServices#executeOperation"); //$NON-NLS-1$ - command.getTasks().add(task); - try { - if (command.canExecute()) { - command.execute(); - } - } finally { - command.dispose(); - } - } - } - } - return eObject; - } - - /** - * Resolves the actual {@link ModelOperation} to execute given its URI. - * - * @param initialCommandUri - * the URI of the operation to search for. - * @param session - * the Sirius session which determines the scope to search into. - * @return the {@link ModelOperation} instance found at the specified URI, - * either in one of the VSMs for which at least one Viewpoint is - * currently enabled in the session, or from the default ruleset, or - * null if no matching operation could be located. - */ - private ModelOperation findModelOperation(String initialCommandUri, Session session) { - URI commandResourceURI = URI.createURI(initialCommandUri).trimFragment(); - for (Resource res : getResourcesInScope(session)) { - if (commandResourceURI.equals(res.getURI())) { - EObject modelOperationEObject = res.getEObject(URI.createURI(initialCommandUri).fragment()); - if (modelOperationEObject instanceof InitialOperation) { - return ((InitialOperation) modelOperationEObject).getFirstModelOperations(); - } - } - } - return null; - } - - /** - * Returns all the (VSM-like) resources in which to search for the - * {@link ModelOperation} to execute. - * - * @param session - * the Sirius session. - * @return all the resources in which to look for the ModelOperation, in - * order of preference. - */ - private Set getResourcesInScope(Session session) { - Set result = new LinkedHashSet<>(); - Collection selectedViewpoints = session.getSelectedViewpoints(true); - for (Viewpoint viewpoint : selectedViewpoints) { - Resource eResource = viewpoint.eResource(); - if (eResource != null) { - result.add(eResource); - } - } - ViewExtensionDescription defaults = DefaultRulesProvider.INSTANCE.getDefaultRules(); - if (defaults != null && defaults.eResource() != null) { - result.add(defaults.eResource()); - } - return result; - } - - /** - * Returns the {@link SiriusContext} associated with a - * {@link SiriusInputDescriptor} (typically the "input" variable of the - * properties view). - * - * @param sid - * a {@link SiriusInputDescriptor} (typically the "input" - * variable of the properties view). - * @return the input's full context. - */ - public SiriusContext context(SiriusInputDescriptor sid) { - return sid.getFullContext(); - } - - /** - * Returns the semantic element for the given input descriptor. - * - * @param sid - * The input descriptor - * @return The semantic element for the given input descriptor - */ - public EObject getSemanticElement(SiriusInputDescriptor sid) { - return sid.getSemanticElement(); - } - - /** - * Returns all the semantic elements for the given input descriptor. - * - * @param sid - * The input descriptor - * @return The semantic element for the given input descriptor - */ - public Collection getAllSemanticElements(SiriusInputDescriptor sid) { - return sid.getAllSemanticElements(); - } - - /** - * Returns the original selection for the given input descriptor. - * - * @param sid - * The input descriptor - * @return The original selection for the given input descriptor - */ - public Object getOriginalSelection(SiriusInputDescriptor sid) { - return sid.getOriginalSelection(); - } - - /** - * Returns the Sirius session associated to a given context. - * - * @param ctx - * a Sirius context. - * - * @return the Sirius session associated to a given context. - */ - public Session session(SiriusContext ctx) { - Option s = ctx.getSession(); - if (s.some()) { - return s.get(); - } else { - return null; - } - } - - /** - * Returns the Sirius representation associated to a given context. - * - * @param ctx - * a Sirius context. - * - * @return the Sirius representation associated to a given context. - */ - public DRepresentation representation(SiriusContext ctx) { - Option r = ctx.getDRepresentation(); - if (r.some()) { - return r.get(); - } else { - return null; - } - } - - /** - * Returns the Sirius {@link DSemanticDecorator} associated to a given - * context. - * - * @param ctx - * a Sirius context. - * - * @return the Sirius {@link DSemanticDecorator} associated to a given - * context. - */ - public DSemanticDecorator semanticDecorator(SiriusContext ctx) { - return ctx.getSemanticDecorator(); - } - - /** - * Returns the main semantic element associated to a given context. - * - * @param ctx - * a Sirius context. - * - * @return the main semantic element associated to a given context. - */ - public EObject mainSemanticElement(SiriusContext ctx) { - Option target = ctx.getMainSemanticElement(); - if (target.some()) { - return target.get(); - } else { - return null; - } - } - - /** - * Returns all the semantic elements associated to a given context. - * - * @param ctx - * a Sirius context. - * - * @return all the semantic elements associated to a given context. - */ - public Collection allSemanticElements(SiriusContext ctx) { - Option> elements = ctx.getAdditionalSemanticElements(); - if (elements.some()) { - return elements.get(); - } else { - return null; - } - } - - /** - * Returns a helper with EMF Edit-related operations on a given element. - * - * @param input - * a {@link SiriusInputDescriptor} (typically the "input" - * variable of the properties view). - * @param self - * the target semantic element on which the helper should - * operator. - * @return an instance of EditSupport bounnd to the specified semantic - * element. - */ - public EditSupport emfEditServices(SiriusInputDescriptor input, EObject self) { - EditSupportSpec ess = new EditSupportSpec(input.getFullContext(), self); - return ess; - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/DomainClassSwitch.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/DomainClassSwitch.java deleted file mode 100644 index 12f101056b..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/DomainClassSwitch.java +++ /dev/null @@ -1,207 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal.expressions; - -import java.util.Collection; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.sirius.common.tools.api.interpreter.TypeName; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.ext.base.Options; -import org.eclipse.sirius.properties.CustomExpression; -import org.eclipse.sirius.properties.CustomOperation; -import org.eclipse.sirius.properties.DynamicMappingFor; -import org.eclipse.sirius.properties.DynamicMappingIf; -import org.eclipse.sirius.properties.GroupDescription; -import org.eclipse.sirius.properties.GroupStyle; -import org.eclipse.sirius.properties.OperationDescription; -import org.eclipse.sirius.properties.PageDescription; -import org.eclipse.sirius.properties.PropertiesPackage; -import org.eclipse.sirius.properties.WidgetAction; -import org.eclipse.sirius.properties.WidgetConditionalStyle; -import org.eclipse.sirius.properties.WidgetDescription; -import org.eclipse.sirius.properties.WidgetStyle; -import org.eclipse.sirius.properties.util.PropertiesSwitch; - -import com.google.common.collect.Sets; - -/** - * Computes the domainClass (i.e. expected type of the receiver) for any - * interpreted expression defined on properties views elements. Note that this - * does not handle element inside a properties view description which come from - * other Sirius package (e.g. model operations). - * - * @author pcdavid - */ -public class DomainClassSwitch extends PropertiesSwitch>> { - /** - * Constant used in switches on feature id to consider the case when the - * feature must not be considered. - */ - private static final int DO_NOT_CONSIDER_FEATURE = -1; - - /** - * The feature containing the Interpreted expression. - */ - protected EStructuralFeature feature; - - /** - * Indicates if the feature must be considered. - */ - protected boolean considerFeature; - - /** - * Default constructor. - * - * @param feature - * the feature containing the Interpreted expression - */ - public DomainClassSwitch(EStructuralFeature feature) { - this.feature = feature; - } - - @Override - public Option> doSwitch(EObject theEObject) { - Option> doSwitch = super.doSwitch(theEObject); - if (doSwitch != null) { - return doSwitch; - } - Collection defaultResult = Sets.newLinkedHashSet(); - return Options.newSome(defaultResult); - } - - /** - * Changes the behavior of this switch: if true, then the feature will be - * considered to calculate target types; if false, then the feature will be - * ignored. - * - * @param considerFeature - * true if the feature should be considered, false otherwise - */ - public void setConsiderFeature(boolean considerFeature) { - this.considerFeature = considerFeature; - } - - @Override - public Option> casePageDescription(PageDescription page) { - Option> result = null; - switch (getFeatureId(page.eClass())) { - case PropertiesPackage.PAGE_DESCRIPTION__SEMANTIC_CANDIDATE_EXPRESSION: - /* - * A page can be activated from almost any kind of input: anything - * selectable from any of the representations defined in the same - * VSM can trigger teh evaluation of the page's - * semanticCandidateExpression. Technically we could compute a union - * of all the relevant semantic types, but in practice there is - * little chance that it would be more useful than just EObject. - */ - Collection target = Sets.newLinkedHashSet(); - target.add(TypeName.EOBJECT_TYPENAME.getCompleteName()); - result = Options.newSome(target); - break; - case PropertiesPackage.PAGE_DESCRIPTION__LABEL_EXPRESSION: - case PropertiesPackage.PAGE_DESCRIPTION__PRECONDITION_EXPRESSION: - case DO_NOT_CONSIDER_FEATURE: - result = Options.newSome(VSMNavigation.getPageDomainClass(page)); - break; - default: - break; - } - return result; - } - - @Override - public Option> caseGroupDescription(GroupDescription group) { - Option> result = null; - switch (getFeatureId(group.eClass())) { - case PropertiesPackage.GROUP_DESCRIPTION__SEMANTIC_CANDIDATE_EXPRESSION: - /* - * A Group's semanticCandidateExpression is evaluated from the - * target of its referencing page, which is an instance of the - * page's domainClass. - */ - Collection target = Sets.newLinkedHashSet(); - for (PageDescription page : VSMNavigation.findReferencingPages(group)) { - target.addAll(VSMNavigation.getPageDomainClass(page)); - } - result = Options.newSome(target); - break; - case PropertiesPackage.GROUP_DESCRIPTION__LABEL_EXPRESSION: - case PropertiesPackage.GROUP_DESCRIPTION__PRECONDITION_EXPRESSION: - case DO_NOT_CONSIDER_FEATURE: - result = Options.newSome(VSMNavigation.getGroupDomainClass(group)); - break; - default: - break; - } - return result; - } - - @Override - public Option> caseWidgetDescription(WidgetDescription object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseWidgetStyle(WidgetStyle object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseWidgetConditionalStyle(WidgetConditionalStyle object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseWidgetAction(WidgetAction object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseGroupStyle(GroupStyle object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseCustomExpression(CustomExpression object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseCustomOperation(CustomOperation object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseOperationDescription(OperationDescription object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseDynamicMappingFor(DynamicMappingFor object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - @Override - public Option> caseDynamicMappingIf(DynamicMappingIf object) { - return VSMNavigation.getDomainClassFromContainingGroup(object); - } - - private int getFeatureId(EClass eClass) { - if (considerFeature && feature != null) { - return eClass.getFeatureID(feature); - } else { - return DomainClassSwitch.DO_NOT_CONSIDER_FEATURE; - } - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesExpressionQueryProvider.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesExpressionQueryProvider.java deleted file mode 100644 index 74e5143bee..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesExpressionQueryProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal.expressions; - -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQuery; -import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQueryProvider; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.ext.base.Options; - -/** - * An {@link IInterpretedExpressionQueryProvider} for properties view - * description expressions. - * - * @author pcdavid - */ -public class PropertiesExpressionQueryProvider implements IInterpretedExpressionQueryProvider { - @Override - public Option getExpressionQueryFor(EObject context, EStructuralFeature expressionAttribute) { - if (VSMNavigation.isInsideViewExtensionDescription(context)) { - IInterpretedExpressionQuery value = new PropertiesInterpretedExpressionQuery(context, expressionAttribute); - return Options.newSome(value); - } else { - return Options.newNone(); - } - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesInterpretedExpressionQuery.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesInterpretedExpressionQuery.java deleted file mode 100644 index 00d26c4a8e..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/PropertiesInterpretedExpressionQuery.java +++ /dev/null @@ -1,399 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal.expressions; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -import org.eclipse.eef.common.api.utils.Util; -import org.eclipse.eef.core.api.EEFExpressionUtils; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.EAttribute; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EPackage.Registry; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EcorePackage; -import org.eclipse.sirius.business.api.dialect.description.AbstractInterpretedExpressionQuery; -import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionQuery; -import org.eclipse.sirius.business.api.dialect.description.IInterpretedExpressionTargetSwitch; -import org.eclipse.sirius.business.api.dialect.description.MultiLanguagesValidator; -import org.eclipse.sirius.business.api.query.EObjectQuery; -import org.eclipse.sirius.business.internal.dialect.description.ToolInterpretedExpressionTargetSwitch; -import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext; -import org.eclipse.sirius.common.tools.api.interpreter.TypeName; -import org.eclipse.sirius.common.tools.api.interpreter.ValidationResult; -import org.eclipse.sirius.common.tools.api.interpreter.VariableType; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.ext.base.Options; -import org.eclipse.sirius.properties.DynamicMappingFor; -import org.eclipse.sirius.properties.GroupDescription; -import org.eclipse.sirius.properties.PageDescription; -import org.eclipse.sirius.properties.PropertiesPackage; -import org.eclipse.sirius.properties.ViewExtensionDescription; -import org.eclipse.sirius.tools.api.interpreter.context.SiriusInterpreterContextFactory; -import org.eclipse.sirius.ui.properties.internal.SiriusInputDescriptor; -import org.eclipse.sirius.ui.properties.internal.SiriusToolServices; -import org.eclipse.sirius.viewpoint.ViewpointPackage; -import org.eclipse.sirius.viewpoint.description.DescriptionPackage; -import org.eclipse.sirius.viewpoint.description.Extension; -import org.eclipse.sirius.viewpoint.description.Group; -import org.eclipse.sirius.viewpoint.description.RepresentationDescription; -import org.eclipse.sirius.viewpoint.description.tool.InitialOperation; -import org.eclipse.sirius.viewpoint.description.tool.ToolPackage; -import org.eclipse.sirius.viewpoint.description.validation.ValidationPackage; - -import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -/** - * An {@code IInterpretedExpressionQuery} for expressions occuring inside - * properties view descriptions. - * - * @author pcdavid - */ -public final class PropertiesInterpretedExpressionQuery extends AbstractInterpretedExpressionQuery implements IInterpretedExpressionQuery { - private Collection packagesToImport; - - /** - * Constructor. - * - * @param target - * the VSM element on which the expression appears. - * @param expressionAttribute - * the attribute of the VSM element which defines the expression - * (assumed to be an InterpredExpression). - */ - public PropertiesInterpretedExpressionQuery(EObject target, EStructuralFeature expressionAttribute) { - super(target, expressionAttribute); - } - - @Override - protected void initializeTargetSwitch() { - this.targetSwitch = new PropertiesExpressionsGlobalTargetSwitch(feature); - } - - @Override - public Collection getPackagesToImport() { - /* - * We can't rely on the default implementation here, as it assumes we - * are inside a RepresentationDescription, which is not the case for - * properties definitions. - */ - if (packagesToImport == null) { - packagesToImport = PropertiesInterpretedExpressionQuery.getEPackagesInScope(target); - } - return packagesToImport; - } - - @Override - public Collection getDependencies() { - /* - * We can't rely on the default implementation here, as it assumes we - * are inside a Viewpoint, which is not the case for properties - * definitions. - */ - if (dependencies == null) { - Collection result = Lists.newArrayList(VSMNavigation.getJavaExtensionsInVSM(target)); - // Make sure the implicitly registered SiriusToolServices class is - // also visible. - result.add(SiriusToolServices.class.getName()); - dependencies = result; - } - return dependencies; - } - - private static Collection getEPackagesInScope(EObject target) { - Collection result = Sets.newLinkedHashSet(); - - boolean needsGlobalPackages = false; - for (RepresentationDescription desc : VSMNavigation.getRepresentationDescriptionsInVSM(target)) { - EList configured = desc.getMetamodel(); - result.addAll(configured); - if (configured.isEmpty()) { - /* - * If at least one of the possible source representations has no - * explicitly configured metamodel, we must include the globally - * registered packages. - */ - needsGlobalPackages = true; - } - } - - if (needsGlobalPackages) { - result.addAll(PropertiesInterpretedExpressionQuery.getAllRegisteredEPackages(EPackage.Registry.INSTANCE)); - } - - // Also add metamodels explicitly added to the ViewExtensionDescription, - // if any. - Option viewDescriptionOpt = new EObjectQuery(target).getFirstAncestorOfType(PropertiesPackage.Literals.VIEW_EXTENSION_DESCRIPTION); - if (viewDescriptionOpt.some()) { - ViewExtensionDescription ved = (ViewExtensionDescription) viewDescriptionOpt.get(); - result.addAll(ved.getMetamodels()); - } - - // In all cases, we make sure the core Sirius metamodels are present... - result.add(EcorePackage.eINSTANCE); - result.add(ViewpointPackage.eINSTANCE); - result.add(DescriptionPackage.eINSTANCE); - result.add(ToolPackage.eINSTANCE); - result.add(ValidationPackage.eINSTANCE); - // ... and the properties view one too. - result.add(PropertiesPackage.eINSTANCE); - - return result; - } - - private static Collection getAllRegisteredEPackages(Registry source) { - Collection result = Sets.newLinkedHashSet(); - for (String nsURI : Sets.newLinkedHashSet(source.keySet())) { - try { - result.add(source.getEPackage(nsURI)); - // CHECKSTYLE:OFF - } catch (Throwable e) { - /* - * anything might happen here depending on the other Eclipse - * tools, and we've seen many time tools breaking all the - * others. - */ - // CHECKSTYLE:ON - } - } - return result; - } - - @Override - public Map getAvailableVariables() { - if (availableVariables == null) { - availableVariables = Maps.newLinkedHashMap(); - } - - // going through eContainer() to declare any For variable (dynamic - // mappings) - EObject cur = target; - while (!(cur instanceof Group) && cur != null) { - EObject parent = cur.eContainer(); - if (parent instanceof DynamicMappingFor) { - String iteratorName = ((DynamicMappingFor) parent).getIterator(); - if (!Util.isBlank(iteratorName)) { - VariableType iteratorType = getResultType(parent, PropertiesPackage.Literals.DYNAMIC_MAPPING_FOR__ITERABLE_EXPRESSION); - availableVariables.put(iteratorName, iteratorType); - } - } - cur = parent; - } - - if (isFromOrInheritsPropertiesEPackage(this.target)) { - // "input" is always available. - availableVariables.put(EEFExpressionUtils.INPUT, VariableType.fromJavaClass(SiriusInputDescriptor.class)); - - if (feature == PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATE_DISPLAY_EXPRESSION) { - VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATES_EXPRESSION); - availableVariables.put(EEFExpressionUtils.EEFSelect.CANDIDATE, candidatesExpressionType); - } else if (feature == PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATE_DISPLAY_EXPRESSION) { - VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATES_EXPRESSION); - availableVariables.put(EEFExpressionUtils.EEFSelect.CANDIDATE, candidatesExpressionType); - } else if (feature == PropertiesPackage.Literals.LABEL_DESCRIPTION__DISPLAY_EXPRESSION) { - VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.LABEL_DESCRIPTION__VALUE_EXPRESSION); - availableVariables.put(EEFExpressionUtils.EEFReference.VALUE, candidatesExpressionType); - } else if (feature == PropertiesPackage.Literals.LIST_DESCRIPTION__DISPLAY_EXPRESSION) { - VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.LIST_DESCRIPTION__VALUE_EXPRESSION); - availableVariables.put(EEFExpressionUtils.EEFList.VALUE, candidatesExpressionType); - } else if (feature == PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__DISPLAY_EXPRESSION) { - VariableType candidatesExpressionType = getResultType(target, PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__VALUE_EXPRESSION); - availableVariables.put(EEFExpressionUtils.EEFReference.VALUE, candidatesExpressionType); - } else if (feature == PropertiesPackage.Literals.DYNAMIC_MAPPING_IF__PREDICATE_EXPRESSION) { - if (target.eContainer() instanceof DynamicMappingFor) { - DynamicMappingFor forDefinition = (DynamicMappingFor) target.eContainer(); - String iteratorName = forDefinition.getIterator(); - if (!Util.isBlank(iteratorName)) { - VariableType iteratorType = getResultType(forDefinition, PropertiesPackage.Literals.DYNAMIC_MAPPING_FOR__ITERABLE_EXPRESSION); - availableVariables.put(iteratorName, iteratorType); - } - } - } - return availableVariables; - } else { - return super.getAvailableVariables(); - } - } - - /** - * return true if the given EObject is from PropertiesPackage or inherits - * from one of the EClasses of PropertiesPackage. - * - * @param object - * any EObject - * @return true if the given EObject is from PropertiesPackage or inherits - * from one of the EClasses of PropertiesPackage - */ - private boolean isFromOrInheritsPropertiesEPackage(EObject object) { - boolean isPropertiesElement = false; - Iterator it = Iterators.concat(Iterators.singletonIterator(object.eClass()), object.eClass().getEAllSuperTypes().iterator()); - while (!isPropertiesElement && it.hasNext()) { - isPropertiesElement = it.next().getEPackage() == PropertiesPackage.eINSTANCE; - } - return isPropertiesElement; - } - - @Override - protected Option getToolContext() { - Option result = super.getToolContext(); - if (!result.some()) { - if (target instanceof PageDescription || target instanceof GroupDescription) { - result = Options.newSome(target); - } else { - result = new EObjectQuery(target).getFirstAncestorOfType(ToolPackage.Literals.INITIAL_OPERATION); - } - } - return result; - } - - @Override - protected void addVariablesFromToolContext(EObject toolContext) { - super.addVariablesFromToolContext(toolContext); - availableVariables.put(EEFExpressionUtils.INPUT, VariableType.fromJavaClass(SiriusInputDescriptor.class)); - if (toolContext instanceof InitialOperation) { - EReference callbackFeature = toolContext.eContainmentFeature(); - VariableType stringType = VariableType.fromString("java.lang.String"); //$NON-NLS-1$ - VariableType booleanType = VariableType.fromString("java.lang.Boolean"); //$NON-NLS-1$ - VariableType unkownType = VariableType.fromString(TypeName.EOBJECT_TYPENAME.getCompleteName()); - if (callbackFeature == PropertiesPackage.Literals.TEXT_DESCRIPTION__INITIAL_OPERATION) { - availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, stringType); - } else if (callbackFeature == PropertiesPackage.Literals.CHECKBOX_DESCRIPTION__INITIAL_OPERATION) { - availableVariables.put(EEFExpressionUtils.EEFCheckbox.NEW_VALUE, booleanType); - } else if (callbackFeature == PropertiesPackage.Literals.HYPERLINK_DESCRIPTION__INITIAL_OPERATION) { - Option> domainClass = VSMNavigation.getDomainClassFromContainingGroup(toolContext); - if (domainClass.some()) { - availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, VariableType.fromStrings(domainClass.get())); - } else { - availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, unkownType); - } - } else if (callbackFeature == PropertiesPackage.Literals.RADIO_DESCRIPTION__INITIAL_OPERATION) { - /* - * in the case of the radio button the type of newValue is the - * return type of the candidate expression. - */ - availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, getResultType(toolContext.eContainer(), PropertiesPackage.Literals.RADIO_DESCRIPTION__CANDIDATES_EXPRESSION)); - } else if (callbackFeature == PropertiesPackage.Literals.WIDGET_ACTION__INITIAL_OPERATION) { - Option> domainClass = VSMNavigation.getDomainClassFromContainingGroup(toolContext); - if (!domainClass.some()) { - availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, VariableType.fromStrings(domainClass.get())); - } else { - availableVariables.put(EEFExpressionUtils.EEFHyperlink.SELECTION, unkownType); - } - } else if (callbackFeature == PropertiesPackage.Literals.SELECT_DESCRIPTION__INITIAL_OPERATION) { - availableVariables.put(EEFExpressionUtils.EEFText.NEW_VALUE, getResultType(toolContext.eContainer(), PropertiesPackage.Literals.SELECT_DESCRIPTION__CANDIDATES_EXPRESSION)); - } - } - } - - private VariableType getResultType(EObject owner, EAttribute attr) { - IInterpreterContext context = SiriusInterpreterContextFactory.createInterpreterContext(owner, attr); - ValidationResult res = MultiLanguagesValidator.getInstance().validateExpression(context, (String) owner.eGet(attr)); - return res.getReturnTypes(); - } - - /** - * The switch used to compute domainClasses for expressions used in - * properties definitions. - * - * @author pcdavid - */ - private static class PropertiesExpressionsGlobalTargetSwitch implements IInterpretedExpressionTargetSwitch { - /** - * The switch for properties-specific expressions. - */ - private final DomainClassSwitch propertiesSwitch; - - /** - * The switch we delegate to for Model Operations. - */ - private final ToolInterpretedExpressionTargetSwitch delegateSwitch; - - /** - * By default ToolInterpretedExpressionTargetSwitch assumes operations - * will appear inside representations or mappings, so we override - * getFirstContextChangingContainer() to locate the parent - * GroupDescription instead. - */ - private static class CustomToolInterpretedExpressionTargetSwitch extends ToolInterpretedExpressionTargetSwitch { - public CustomToolInterpretedExpressionTargetSwitch(EStructuralFeature feature, IInterpretedExpressionTargetSwitch defaultSwitch) { - super(feature, defaultSwitch); - } - - @Override - protected EObject getFirstContextChangingContainer(EObject element) { - EObject defaultResult = super.getFirstContextChangingContainer(element); - if (defaultResult instanceof Extension) { - /* - * The generic algorithm in the super-class does not know - * anything about the properties metamodel but will stop at - * the top-level ViewExtensionDescription as it is an - * Extension. - */ - return VSMNavigation.findClosestGroupDescription(element); - } else { - return defaultResult; - } - } - } - - public PropertiesExpressionsGlobalTargetSwitch(EStructuralFeature feature) { - this.propertiesSwitch = new DomainClassSwitch(feature); - this.delegateSwitch = new CustomToolInterpretedExpressionTargetSwitch(feature, this); - } - - @Override - public Option> doSwitch(EObject target, boolean considerFeature) { - Collection targetTypes = Sets.newLinkedHashSet(); - Option> expressionTarget = Options.newSome(targetTypes); - if (target != null) { - if (expressionTarget.some() && expressionTarget.get().isEmpty()) { - propertiesSwitch.setConsiderFeature(considerFeature); - expressionTarget = propertiesSwitch.doSwitch(target); - } - if (expressionTarget.some() && expressionTarget.get().isEmpty()) { - delegateSwitch.setConsiderFeature(considerFeature); - expressionTarget = delegateSwitch.doSwitch(target); - } - } - return expressionTarget; - } - - @Override - public EObject getFirstRelevantContainer(EObject obj) { - if (obj != null) { - EObject container = obj.eContainer(); - while (container != null && !isRelevant(container)) { - container = container.eContainer(); - } - return container; - } else { - return null; - } - } - - /** - * In this context, relevant containers are top-level pages and groups - * only. The root ViewExtensionDescriptions do not define anything - * relevant for domain class computation. - */ - private boolean isRelevant(EObject container) { - return container instanceof PageDescription || container instanceof GroupDescription; - } - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/VSMNavigation.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/VSMNavigation.java deleted file mode 100644 index 2513a251d2..0000000000 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/expressions/VSMNavigation.java +++ /dev/null @@ -1,208 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Obeo. - * 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.ui.properties.internal.expressions; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; - -import org.eclipse.eef.common.api.utils.Util; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.sirius.business.api.query.EObjectQuery; -import org.eclipse.sirius.common.tools.api.interpreter.TypeName; -import org.eclipse.sirius.common.tools.api.util.StringUtil; -import org.eclipse.sirius.ext.base.Option; -import org.eclipse.sirius.ext.base.Options; -import org.eclipse.sirius.properties.GroupDescription; -import org.eclipse.sirius.properties.PageDescription; -import org.eclipse.sirius.properties.PropertiesPackage; -import org.eclipse.sirius.properties.ViewExtensionDescription; -import org.eclipse.sirius.viewpoint.description.DescriptionPackage; -import org.eclipse.sirius.viewpoint.description.Group; -import org.eclipse.sirius.viewpoint.description.JavaExtension; -import org.eclipse.sirius.viewpoint.description.RepresentationDescription; -import org.eclipse.sirius.viewpoint.description.Viewpoint; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -/** - * Utility methods to navigate inside a VSM, especially wrt properties - * descriptions. - * - * @author pcdavid - */ -public final class VSMNavigation { - private VSMNavigation() { - // Preven instanciation. - } - - /** - * Tests whether a model element is part of a Sirius properties view - * description. - * - * @param vsmElement - * the element to test. - * @return true if the element is part of a Sirius properties - * view description. - */ - public static boolean isInsideViewExtensionDescription(EObject vsmElement) { - return new EObjectQuery(vsmElement).getFirstAncestorOfType(PropertiesPackage.Literals.VIEW_EXTENSION_DESCRIPTION).some(); - } - - /** - * Returns the domain class of a given {@link PageDescription}, defaulting - * to a generic catch-all type if no value was set explicitly. - * - * @param page - * a {@link PageDescription}. - * @return the names of potential domain classes for that page. - */ - public static Collection getPageDomainClass(PageDescription page) { - if (page != null && !Util.isBlank(page.getDomainClass())) { - return Collections.singleton(page.getDomainClass()); - } else { - return Collections.singleton(TypeName.EOBJECT_TYPENAME.getCompleteName()); - } - } - - /** - * Returns the domain class of a given {@link GroupDescription}, defaulting - * to the union of all the possible domain classes from pages which - * reference that group if no value was set explicitly. - * - * @param group - * a {@link GroupDescription}. - * @return the names of potential domain classes for that group. - */ - public static Collection getGroupDomainClass(GroupDescription group) { - if (group != null && !Util.isBlank(group.getDomainClass())) { - return Collections.singleton(group.getDomainClass()); - } else { - Collection result = Sets.newLinkedHashSet(); - for (PageDescription page : VSMNavigation.findReferencingPages(group)) { - result.addAll(getPageDomainClass(page)); - } - return result; - } - } - - /** - * Returns the domain class of a VSM element from inside a - * {@link GroupDescription} (for example a widget). - * - * @param vsmElement - * the VSM element. - * @return the domain class of the VSM element, as determined by the - * enclosing {@link GroupDescription}. - */ - public static Option> getDomainClassFromContainingGroup(EObject vsmElement) { - Option> result = Options.newNone(); - GroupDescription group = VSMNavigation.findClosestGroupDescription(vsmElement); - if (group != null) { - result = Options.newSome(getGroupDomainClass(group)); - } - return result; - } - - /** - * Get all the representation description defined in the same VSM as a given - * element. - * - * @param vsmElement - * a VSM element. - * @return all the representation description defined in the same VSM. - */ - public static Collection getRepresentationDescriptionsInVSM(EObject vsmElement) { - Collection result = Lists.newArrayList(); - Option answer = getVSMRoot(vsmElement); - if (answer.some()) { - Group group = (Group) answer.get(); - for (Viewpoint viewpoint : group.getOwnedViewpoints()) { - result.addAll(viewpoint.getOwnedRepresentations()); - } - } - return result; - } - - /** - * Finds all the Java extensions registered in the VSM of the specified - * element. - * - * @param vsmElement - * an element from a VSM model. - * @return the qualified names of all the Java extensions registered in the - * same VSM. - */ - public static Collection getJavaExtensionsInVSM(EObject vsmElement) { - Collection result = Lists.newArrayList(); - Option answer = getVSMRoot(vsmElement); - if (answer.some()) { - Group group = (Group) answer.get(); - for (Viewpoint vp : group.getOwnedViewpoints()) { - for (JavaExtension dep : vp.getOwnedJavaExtensions()) { - if (!StringUtil.isEmpty(dep.getQualifiedClassName())) { - result.add(dep.getQualifiedClassName()); - } - } - } - } - return result; - } - - private static Option getVSMRoot(EObject vsmElement) { - return new EObjectQuery(vsmElement).getFirstAncestorOfType(DescriptionPackage.Literals.GROUP); - } - - /** - * Find which pages reference a given group in a VSM. Groups are not - * contained insides pages, but referenced from pages defined inside the - * same {@link ViewExtensionDescription}. - * - * @param group - * a group. - * @return all the pages inside the same ViewExtensionDescription as the - * group that reference it. - */ - public static Set findReferencingPages(GroupDescription group) { - EObject container = group.eContainer(); - if (container instanceof ViewExtensionDescription) { - ViewExtensionDescription ved = (ViewExtensionDescription) container; - Set result = Sets.newLinkedHashSet(); - for (PageDescription page : ved.getPages()) { - if (page.getGroups().contains(group)) { - result.add(page); - } - } - return result; - } else { - return Collections.emptySet(); - } - } - - /** - * Returns the {@link GroupDescription} enclosing a given VSM element, if - * any. - * - * @param vsmElement - * a VSM element. - * @return the {@link GroupDescription} enclosing the element, or - * null if none could be found. - */ - public static GroupDescription findClosestGroupDescription(EObject vsmElement) { - if (vsmElement instanceof GroupDescription) { - return (GroupDescription) vsmElement; - } else { - Option answer = new EObjectQuery(vsmElement).getFirstAncestorOfType(PropertiesPackage.Literals.GROUP_DESCRIPTION); - return answer.some() ? (GroupDescription) answer.get() : null; - } - } -} diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/SiriusTabDescriptorProvider.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/SiriusTabDescriptorProvider.java index ce1feacd07..4c596ce7b1 100644 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/SiriusTabDescriptorProvider.java +++ b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/SiriusTabDescriptorProvider.java @@ -38,7 +38,7 @@ import org.eclipse.sirius.ext.base.Option; import org.eclipse.sirius.properties.PageDescription; import org.eclipse.sirius.properties.ViewExtensionDescription; import org.eclipse.sirius.properties.core.api.DefaultRulesProvider; -import org.eclipse.sirius.ui.properties.internal.SiriusInputDescriptor; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; import org.eclipse.sirius.ui.properties.internal.SiriusInterpreter; import org.eclipse.sirius.ui.properties.internal.SiriusUIPropertiesPlugin; import org.eclipse.sirius.viewpoint.description.DescriptionPackage; diff --git a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/ViewDescriptionConverter.java b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/ViewDescriptionConverter.java index 3192b66198..9f3c938943 100644 --- a/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/ViewDescriptionConverter.java +++ b/plugins/org.eclipse.sirius.ui.properties/src/org/eclipse/sirius/ui/properties/internal/tabprovider/ViewDescriptionConverter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2016 Obeo. + * Copyright (c) 2015, 2017 Obeo. * 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 @@ -25,10 +25,10 @@ import org.eclipse.emf.ecore.EPackage; import org.eclipse.sirius.properties.GroupDescription; import org.eclipse.sirius.properties.PageDescription; import org.eclipse.sirius.properties.ViewExtensionDescription; +import org.eclipse.sirius.properties.core.api.SiriusInputDescriptor; import org.eclipse.sirius.ui.properties.api.DescriptionCache; import org.eclipse.sirius.ui.properties.api.IDescriptionConverter; import org.eclipse.sirius.ui.properties.api.IDescriptionLinkResolver; -import org.eclipse.sirius.ui.properties.internal.SiriusInputDescriptor; import org.eclipse.sirius.ui.properties.internal.SiriusUIPropertiesPlugin; /** diff --git a/plugins/org.eclipse.sirius.ui/src-gen/org/eclipse/sirius/viewpoint/provider/SiriusEditPlugin.java b/plugins/org.eclipse.sirius.ui/src-gen/org/eclipse/sirius/viewpoint/provider/SiriusEditPlugin.java index 16d2651b22..024579a119 100644 --- a/plugins/org.eclipse.sirius.ui/src-gen/org/eclipse/sirius/viewpoint/provider/SiriusEditPlugin.java +++ b/plugins/org.eclipse.sirius.ui/src-gen/org/eclipse/sirius/viewpoint/provider/SiriusEditPlugin.java @@ -154,8 +154,6 @@ public final class SiriusEditPlugin extends EMFPlugin { private Map descriptorsToImages; - private UICallBack uiCallback = new GenericSWTCallBack(); - private Multimap propertySheetPageProviders = HashMultimap.create(); /** @@ -185,6 +183,7 @@ public final class SiriusEditPlugin extends EMFPlugin { // Remember the static instance. // SiriusEditPlugin.plugin = this; + SiriusPlugin.getDefault().setUiCallback(new GenericSWTCallBack()); } /** @@ -516,7 +515,7 @@ public final class SiriusEditPlugin extends EMFPlugin { * @return the uiCallback */ public UICallBack getUiCallback() { - return uiCallback; + return SiriusPlugin.getDefault().getUiCallback(); } /** @@ -526,7 +525,7 @@ public final class SiriusEditPlugin extends EMFPlugin { * the uiCallback to set */ public void setUiCallback(UICallBack uiCallback) { - this.uiCallback = uiCallback; + SiriusPlugin.getDefault().setUiCallback(uiCallback); } } diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/SiriusPlugin.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/SiriusPlugin.java index 900fe402ef..b8cdb9f08e 100644 --- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/SiriusPlugin.java +++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/viewpoint/SiriusPlugin.java @@ -28,6 +28,7 @@ import org.eclipse.sirius.business.internal.helper.delete.DeleteHookDescriptorRe import org.eclipse.sirius.business.internal.resource.strategy.ResourceStrategyRegistryListener; import org.eclipse.sirius.business.internal.session.factory.SessionFactoryRegistryListener; import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessorsRegistry; +import org.eclipse.sirius.tools.api.command.ui.UICallBack; import org.eclipse.sirius.tools.api.interpreter.InterpreterRegistry; import org.eclipse.sirius.tools.internal.ui.ExternalJavaActionRegistryListener; import org.eclipse.sirius.tools.internal.validation.EValidatorAdapter; @@ -136,6 +137,11 @@ public final class SiriusPlugin extends EMFPlugin { */ private InterpretedExpressionQueryProviderRegistry expressionQueryProviderRegistry; + /** + * The user interface callback. + */ + private UICallBack uiCallback; + /** * Creates an instance. */ @@ -257,6 +263,25 @@ public final class SiriusPlugin extends EMFPlugin { } } + /** + * Return callBack. + * + * @return the uiCallback + */ + public UICallBack getUiCallback() { + return uiCallback; + } + + /** + * Modify callBack. + * + * @param uiCallback + * the uiCallback to set + */ + public void setUiCallback(UICallBack uiCallback) { + this.uiCallback = uiCallback; + } + } } -- cgit v1.2.3