/***************************************************************************** * Copyright (c) 2012 CEA LIST. * * 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.infra.emf.providers.strategy; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.facet.infra.facet.FacetReference; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.papyrus.infra.emf.utils.EMFHelper; import org.eclipse.papyrus.infra.widgets.providers.IAdaptableContentProvider; import org.eclipse.papyrus.infra.widgets.strategy.ProviderBasedBrowseStrategy; import org.eclipse.swt.widgets.TreeItem; /** * A TreeBrowseStrategy based on the semantic model. * It can also retrieve a semantic element in a MoDisco tree, when the tree structure is close * to the semantic one (With optional EReferences). * * Container1::Container2::EObject1 can be retrieved in a Tree representing * Container1::(Reference1)::Container2::(Reference2)::EObject1 * * @author Camille Letavernier */ public class ContainmentBrowseStrategy extends ProviderBasedBrowseStrategy { protected IAdaptableContentProvider adaptableProvider; protected TreeViewer viewer; public ContainmentBrowseStrategy(ITreeContentProvider provider) { if(!(provider instanceof IAdaptableContentProvider)) { throw new IllegalArgumentException("The provider must be an IAdaptableContentProvider"); } setProvider(provider); this.adaptableProvider = (IAdaptableContentProvider)super.provider; } // // Elements filtering // @Override protected boolean browseElement(Object containerElement) { Object semanticElement = adaptableProvider.getAdaptedValue(containerElement); if(semanticElement instanceof EReference && !(semanticElement instanceof FacetReference)) { //Only browse Containment references and Facet references return ((EReference)semanticElement).isContainment(); } return true; } // // Elements search // // /** // * {@inheritDoc} // */ // @Override // public TreePath findPath(Object semanticElement, Object[] rootElements) { // List<Object> semanticPath = new LinkedList<Object>(); // findSemanticPath(semanticElement, semanticPath); // return searchPath(semanticPath, rootElements); // } // /** // * Fills the semantic path to the given element // * // * @param element // * The element to retrieve // * @param currentPath // * The path to fill (in-out) // */ // protected void findSemanticPath(Object element, List<Object> currentPath) { // if(element != null && element instanceof EObject) { // findSemanticPath(getSemanticParent(element), currentPath); // currentPath.add(element); // } // } // // protected Object getSemanticParent(Object element) { // if(element instanceof EObject) { // return ((EObject)element).eContainer(); // } // return null; // } // // /** // * Retrieve the graphical TreePath from the given semantic path // * // * @param semanticPath // * @return // */ // protected TreePath searchPath(List<Object> semanticPath, Object input) { // List<Object> graphicalPath = new LinkedList<Object>(); // Object[] graphicalRootObjects = (Object[])input; // if(!searchPath(semanticPath, graphicalPath, graphicalRootObjects)) { // //Object not found // graphicalPath.clear(); // } // // return new TreePath(graphicalPath.toArray()); // } // // protected boolean searchPath(List<Object> semanticPath, List<Object> graphicalPath, Object[] graphicalRootObjects) { // if(semanticPath.isEmpty()) { // return true; // } // // if(graphicalRootObjects == null) { // return false; // } // // Object currentElement = semanticPath.get(0); // for(Object graphicalElement : graphicalRootObjects) { // Object semanticValue = adaptableProvider.getAdaptedValue(graphicalElement); // // //Specific case for containment EReference // if(semanticValue instanceof EReference) { // EReference referenceToBrowse = (EReference)semanticValue; // if(referenceToBrowse.isContainment()) { // graphicalPath.add(graphicalElement); // // if(searchPath(semanticPath, graphicalPath, provider.getChildren(graphicalElement))) { // //The element has been found // return true; // } // // //The element has not been found ; we revert the modifications // graphicalPath.remove(graphicalElement); // } // } // // if(semanticValue == currentElement) { // semanticPath.remove(0); // graphicalPath.add(graphicalElement); // if(searchPath(semanticPath, graphicalPath, provider.getChildren(graphicalElement))) { // return true; // } // } // } // // return false; // } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if(viewer instanceof TreeViewer) { this.viewer = (TreeViewer)viewer; } super.inputChanged(viewer, oldInput, newInput); } /** * {@inheritDoc} */ @Override public void revealSemanticElement(List<?> elementList) { //for each element we reveal it Iterator<?> elementListIterator = elementList.iterator(); ArrayList<Object> treeElementToSelect = new ArrayList<Object>(); while(elementListIterator.hasNext()) { Object currentElement = elementListIterator.next(); //test if the type is an EObject if(currentElement instanceof EObject) { EObject currentEObject = (EObject)currentElement; //the content provider exist? if(provider != null) { //need the root in order to find all element in the tree Object root = provider.getElements(null)[0]; //look for the path in order to access to this element List<Object> path = searchPath(currentEObject, Arrays.asList(provider.getElements(root))); if(path.size() > 0) { //expand in the common viewer the path expandItems(path, viewer.getTree().getItems()); treeElementToSelect.add(path.get(path.size() - 1)); } } } selectReveal(new StructuredSelection(treeElementToSelect)); } } public void expandItems(List<Object> treeElementList, TreeItem[] list) { //the treeElement has more tan one element if(treeElementList.size() > 0) { for(int i = 0; i < list.length; i++) { if(list[i].getData() != null && list[i].getData().equals(treeElementList.get(0))) { if(treeElementList.size() > 1) {//Do no expand the last Object[] toexpand = { treeElementList.get(0) }; viewer.setExpandedElements(toexpand); } ArrayList<Object> tmpList = new ArrayList<Object>(); tmpList.addAll(treeElementList); tmpList.remove(tmpList.get(0)); expandItems(tmpList, list[i].getItems()); } } } } public void selectReveal(ISelection selection) { if(viewer != null) { viewer.setSelection(selection, true); } } /** * look for the path the list of element (comes from the content provider) to go the eObject * * @param eobject * that we look for. * @param objects * a list of elements where eobject can be wrapped. * @return the list of modelElementItem ( from the root to the element that wrap the eobject) */ protected List<Object> searchPath(EObject eobject, List<Object> objects) { List<Object> path = new ArrayList<Object>(); for(Object o : objects) { // Search matches in this level if(!(o instanceof Diagram) && o instanceof IAdaptable) { if(eobject.equals(((IAdaptable)o).getAdapter(EObject.class))) { path.add(o); return path; } } // Find childs only for feature container for(int i = 0; i < provider.getChildren(o).length; i++) { Object treeItem = provider.getChildren(o)[i]; List<Object> tmppath = new ArrayList<Object>(); Object element = EMFHelper.getEObject(treeItem); if(element != null) { if(element instanceof EReference) { if(((EReference)element).isContainment() && (!((EReference)element).isDerived())) { List<Object> childs = new ArrayList<Object>(); childs.add(treeItem); tmppath = searchPath(eobject, childs); } } else { if(element instanceof EObject) { List<Object> childs = new ArrayList<Object>(); childs.add(treeItem); tmppath = searchPath(eobject, childs); } } } // if tmppath contains the wrapped eobject we have find the good path if(tmppath.size() > 0) { if(tmppath.get(tmppath.size() - 1) instanceof IAdaptable) { if(eobject.equals(((IAdaptable)(tmppath.get(tmppath.size() - 1))).getAdapter(EObject.class))) { path.add(o); path.addAll(tmppath); return path; } } } } } return new ArrayList<Object>(); } }