Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/facet/org.eclipse.papyrus.emf.facet.custom.ui/src/org/eclipse/papyrus')
-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
4 files changed, 235 insertions, 2 deletions
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