Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCamille Letavernier2017-11-30 05:17:32 -0500
committerRemi Schnekenburger2018-01-18 04:56:54 -0500
commit8df38d7b8ae96e41bb62753c2e6b5bfaca24e865 (patch)
tree73f711183034db0288594830b539f8f68b6b63ba /plugins/facet
parent5b1553e561d0dd16b071eb32ecd0f76b0e34b4e0 (diff)
downloadorg.eclipse.papyrus-8df38d7b8ae96e41bb62753c2e6b5bfaca24e865.tar.gz
org.eclipse.papyrus-8df38d7b8ae96e41bb62753c2e6b5bfaca24e865.tar.xz
org.eclipse.papyrus-8df38d7b8ae96e41bb62753c2e6b5bfaca24e865.zip
Bug 484648: [Model Explorer] Link with Editor does not work with ME
customized through EMF Facets https://bugs.eclipse.org/bugs/show_bug.cgi?id=484648 Change-Id: I9ac56413a58ce987acf973a87fedba4f1840d632 Signed-off-by: Camille Letavernier <cletavernier@eclipsesource.com>
Diffstat (limited to 'plugins/facet')
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/META-INF/MANIFEST.MF2
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/pom.xml2
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/resources/customproperties.efacet15
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/IContentPropertiesHandler.java7
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/CustomizedTreeContentProvider.java162
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/PropertiesHandler.java11
-rw-r--r--plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/query/DefaultGetParentQuery.java57
7 files changed, 252 insertions, 4 deletions
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/META-INF/MANIFEST.MF b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/META-INF/MANIFEST.MF
index 17b0d363273..84e187da0bb 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/META-INF/MANIFEST.MF
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/META-INF/MANIFEST.MF
@@ -17,7 +17,7 @@ Require-Bundle: org.eclipse.papyrus.emf.facet.custom.core;bundle-version="[3.0.0
org.eclipse.papyrus.emf.facet.common.ui;bundle-version="[1.2.0,2.0.0)"
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
-Bundle-Version: 3.0.0.qualifier
+Bundle-Version: 3.1.0.qualifier
Bundle-Name: %Bundle-Name
Bundle-Activator: org.eclipse.papyrus.emf.facet.custom.ui.internal.Activator
Bundle-ManifestVersion: 2
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/pom.xml b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/pom.xml
index 3a6a7965e49..25a60b3624a 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/pom.xml
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/pom.xml
@@ -7,6 +7,6 @@
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.papyrus.emf.facet.custom.ui</artifactId>
- <version>3.0.0-SNAPSHOT</version>
+ <version>3.1.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project> \ No newline at end of file
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/resources/customproperties.efacet b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/resources/customproperties.efacet
index c3ee21b1070..857d364a02a 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/resources/customproperties.efacet
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/resources/customproperties.efacet
@@ -327,6 +327,21 @@
xsi:type="javaQuery:JavaQuery"
implementationClassName="org.eclipse.papyrus.emf.facet.custom.ui.internal.query.DefaultVisibleAttributesQuery"/>
</facetOperations>
+ <facetOperations
+ name="parent">
+ <eType
+ xsi:type="ecore:EClass"
+ href="http://www.eclipse.org/emf/2002/Ecore#//EObject"/>
+ <eParameters
+ name="eStructuralFeature">
+ <eType
+ xsi:type="ecore:EClass"
+ href="http://www.eclipse.org/emf/2002/Ecore#//ETypedElement"/>
+ </eParameters>
+ <query
+ xsi:type="javaQuery:JavaQuery"
+ implementationClassName="org.eclipse.papyrus.emf.facet.custom.ui.internal.query.DefaultGetParentQuery"/>
+ </facetOperations>
</eClassifiers>
<eClassifiers
xsi:type="efacet:Facet"
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/IContentPropertiesHandler.java b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/IContentPropertiesHandler.java
index 4b513772626..0fbd0ef3c55 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/IContentPropertiesHandler.java
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/IContentPropertiesHandler.java
@@ -51,4 +51,11 @@ public interface IContentPropertiesHandler {
* @return
*/
public FacetOperation getVisibleReferences();
+
+ /**
+ * Return the getParent customization operation
+ *
+ * @return
+ */
+ FacetOperation getParent();
}
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/CustomizedTreeContentProvider.java b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/CustomizedTreeContentProvider.java
index c7fbc21b360..a6ac20b2e7e 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/CustomizedTreeContentProvider.java
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/CustomizedTreeContentProvider.java
@@ -19,11 +19,13 @@
package org.eclipse.papyrus.emf.facet.custom.ui.internal;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -376,19 +378,175 @@ public class CustomizedTreeContentProvider implements ICustomizedTreeContentProv
public Object getParent(final Object element) {
Object result = null;
if (element instanceof TreeElement) {
+ // It's a TreeElement, which means we've already displayed it.
+ // Finding its parent will be easy
final TreeElement treeElement = (TreeElement) element;
result = treeElement.getParent();
+ } else if (element instanceof EObject) {
+ // It's an EObject, meaning we don't know whether it's already
+ // been displayed. Delegate to the #parent custom query
+ EObject modelElement = (EObject) element;
+ result = customGetParent(modelElement);
}
return result;
}
+ /**
+ * Computes the parent TreeElement for a raw model element
+ *
+ * @param modelElement
+ * @return
+ */
+ private TreeElement customGetParent(final EObject modelElement) {
+ // The custom EObject/Facet parent path, without references
+ List<EObject> customParentPath = getModelElementPath(modelElement);
+
+ // The custom EObject/Facet parent path, including references
+ List<TreeElement> fullElementPath = getFullElementPath(customParentPath);
+
+ // Build the full TreeElement path and return the leaf element
+ return getParentTreeElementForPath(fullElementPath);
+ }
+
+ /**
+ * Returns the (customized) hierarchy of model elements until
+ * the given element (Included).
+ *
+ * This may be different from the semantic container path
+ * if the tree structure has been customized (e.g. via custom
+ * facet references)
+ *
+ * This path is the "natural path", i.e. it is unique (Even when the
+ * content provider actually represents a cyclic graph). It is however
+ * not necessarily the shortest path.
+ */
+ private List<EObject> getModelElementPath(final EObject modelElement) {
+
+ // Ordered from child to parent
+ Collection<EObject> customParentPath = new LinkedHashSet<>();
+ customParentPath.add(modelElement);
+
+ EObject currentModelElement = modelElement;
+ try {
+ while (currentModelElement != null) {
+ EObject parent = customManager.getCustomValueOf(currentModelElement, contentHandler.getParent(), EObject.class);
+ if (parent != null) {
+ if (customParentPath.contains(parent)) {
+ String message = "Cyclic path detected when computing the hierarchy for " + modelElement;
+ message += "\nPath: "+customParentPath;
+ message += "This may indicate an inconsistency in the facet/custom implementation(s) of the #parent query";
+ Logger.logError(message, Activator.getDefault());
+ break;
+ }
+ customParentPath.add(parent);
+ }
+ currentModelElement = parent;
+ }
+ } catch (CustomizationException ex) {
+ Logger.logError(ex, Activator.getDefault());
+ }
+
+ List<EObject> parentPath = new ArrayList<>(customParentPath);
+
+ // Order from parent to child
+ Collections.reverse(parentPath);
+ return parentPath;
+ }
+
+ /**
+ * Builds and returns the complete list of TreeElements corresponding
+ * to the given model element path. The resulting path will include the
+ * necessary EReferences (Which may include FacetReferences).
+ */
+ private List<TreeElement> getFullElementPath(Collection<EObject> customParentPath) {
+ List<TreeElement> treePath = new ArrayList<>(); // Contains EObjects and EReferences
+ TreeElement currentPathElement = null;
+ EObject currentSemanticParent = null;
+
+ for (EObject semanticElement : customParentPath) {
+
+ if (currentPathElement == null) {
+ // Root element
+ EObjectCacheElement cacheElement = new EObjectCacheElement(semanticElement, null);
+ currentPathElement = cache.get(cacheElement);
+ if (currentPathElement == null) {
+ currentPathElement = Arrays.stream(getElements(null)) //
+ .filter(EObjectTreeElement.class::isInstance) //
+ .map(EObjectTreeElement.class::cast) //
+ .filter(tree -> tree.getEObject() == semanticElement) //
+ .findAny().orElse(null);
+ }
+ } else {
+
+ TreeElement nextElement = Arrays.stream(getChildren(currentPathElement)) //
+ .filter(EObjectTreeElement.class::isInstance)//
+ .map(EObjectTreeElement.class::cast) //
+ .filter(tree -> tree.getEObject() == semanticElement) //
+ .findAny() //
+ .orElse(null);
+ if (nextElement == null) {
+ // Try references that may contain this element
+ List<EReference> references = getVisibleReferences(currentSemanticParent);
+ for (EReference reference : references) {
+ if (reference.getEType().isInstance(semanticElement)) {
+ // Potential match
+
+ EObjectCacheElement cacheElement = new EObjectCacheElement(reference, currentPathElement);
+ TreeElement cachedElement = cache.get(cacheElement);
+ if (cachedElement == null || false == cachedElement instanceof EReferenceTreeElement) {
+ // Since we called getChildren() earlier, this shouldn't happen
+ System.err.println("Reference is visible but wasn't found");
+ continue;
+ }
+
+ EReferenceTreeElement cachedRef = (EReferenceTreeElement) cachedElement;
+
+ List<EObjectTreeElement> children;
+ if (reference.getUpperBound() == 1) {
+ children = Collections.singletonList(getSingleValuedReferenceChild(reference, currentSemanticParent, cachedElement));
+ } else {
+ children = getMultiValuedReferenceChildren(reference, currentSemanticParent, cachedRef);
+ }
+
+ nextElement = children.stream() //
+ .filter(tree -> tree.getEObject() == semanticElement) //
+ .findAny() //
+ .orElse(null);
+
+ if (nextElement != null) {
+ treePath.add(cachedRef);
+ break;
+ }
+ }
+ }
+ }
+
+ currentPathElement = nextElement;
+ }
+
+ currentSemanticParent = semanticElement;
+ if (currentPathElement != null) {
+ treePath.add(currentPathElement);
+ } else {
+ System.err.println("Invalid root element: " + currentPathElement);
+ }
+ }
+
+ return treePath;
+ }
+
+ private TreeElement getParentTreeElementForPath(List<TreeElement> fullElementPath) {
+ if (fullElementPath.size() < 2) {
+ return null;
+ }
+ return fullElementPath.get(fullElementPath.size() - 2);
+ }
+
@Override
public boolean hasChildren(final Object element) {
return getChildren(element).length > 0;
}
-
-
@Override
public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
if (oldInput != newInput) {
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/PropertiesHandler.java b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/PropertiesHandler.java
index 12a5f4d731b..75e0738af68 100644
--- a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/PropertiesHandler.java
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/PropertiesHandler.java
@@ -54,6 +54,7 @@ public class PropertiesHandler implements IContentPropertiesHandler,
private static final String IS_VISIBLE = "isVisible"; //$NON-NLS-1$
private static final String VISIBLE_REFERENCES = "visibleReferences"; //$NON-NLS-1$
private static final String VISIBLE_ATTRIBUTES = "visibleAttributes"; //$NON-NLS-1$
+ private static final String PARENT = "parent"; //$NON-NLS-1$
private static final String IS_UNDERLINED = "isUnderlined"; //$NON-NLS-1$
private static final String IS_STRUCKTHROUGH = "isStruckthrough"; //$NON-NLS-1$
private static final String TOP_L_OVERLAY = "topLeftOverlay"; //$NON-NLS-1$
@@ -342,4 +343,14 @@ public class PropertiesHandler implements IContentPropertiesHandler,
return getPropertyByName(PropertiesHandler.CUSTOM,
PropertiesHandler.VISIBLE_REFERENCES);
}
+
+ /**
+ * @see org.eclipse.papyrus.emf.facet.custom.ui.IContentPropertiesHandler#getParent()
+ *
+ * @return
+ */
+ @Override
+ public FacetOperation getParent() {
+ return getPropertyByName(PropertiesHandler.CUSTOM, PropertiesHandler.PARENT);
+ }
} \ No newline at end of file
diff --git a/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/query/DefaultGetParentQuery.java b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/query/DefaultGetParentQuery.java
new file mode 100644
index 00000000000..adbd067c07c
--- /dev/null
+++ b/plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus/emf/facet/custom/ui/internal/query/DefaultGetParentQuery.java
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * Copyright (c) 2017 EclipseSource and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * EclipseSource - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.emf.facet.custom.ui.internal.query;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.papyrus.emf.facet.efacet.core.IFacetManager;
+import org.eclipse.papyrus.emf.facet.efacet.core.exception.DerivedTypedElementException;
+import org.eclipse.papyrus.emf.facet.query.java.core.IJavaQuery2;
+import org.eclipse.papyrus.emf.facet.query.java.core.IParameterValueList2;
+
+/**
+ * <p>
+ * Default implementation of the #parent customization operation. This implementation
+ * returns the {@link EObject#eContainer() EObject's container}.
+ * </p>
+ * <p>
+ * The #parent customization operation is used to customize the behavior of {@link ITreeContentProvider#getParent(Object)},
+ * used to efficiently reveal elements in a custom tree structure.
+ * </p>
+ * <p>
+ * This default implementation is sufficient when displaying the natural containment tree,
+ * even if the intermediate references are customized. It should however be customized when
+ * removing natural containers (e.g. when simplifying the tree structure) or introducing
+ * a custom containment tree (e.g. when moving an element to a different parent)
+ * </p>
+ *
+ * @since 3.1
+ */
+public class DefaultGetParentQuery implements IJavaQuery2<EObject, EObject> {
+
+ /**
+ * @see org.eclipse.papyrus.emf.facet.query.java.core.IJavaQuery2#evaluate(org.eclipse.emf.ecore.EObject, org.eclipse.papyrus.emf.facet.query.java.core.IParameterValueList2, org.eclipse.papyrus.emf.facet.efacet.core.IFacetManager)
+ *
+ * @param source
+ * @param parameterValues
+ * @param facetManager
+ * @return
+ * @throws DerivedTypedElementException
+ */
+ @Override
+ public EObject evaluate(EObject source, IParameterValueList2 parameterValues, IFacetManager facetManager) throws DerivedTypedElementException {
+ return source.eContainer();
+ }
+
+}

Back to the top