/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.core.workspace; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.emf.ecore.EObject; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.designer.core.ModelEditor; import org.teiid.designer.core.ModelerCore; /** * The ModelWorkspaceView represents a filtered view of the {@link ModelWorkspace}, including the contents of models. * * @since 8.0 */ public class ModelWorkspaceView { public static final boolean DEFAULT_RESTRICT_TO_MODEL_RESOURCES_ONLY = true; /** * A reusable filter that shows everything in the view. */ public static final ModelWorkspaceFilter SHOW_ALL_FILTER = new ModelWorkspaceFilter() { @Override public boolean select( Object parentElement, Object element ) { return true; } }; private static final Object[] EMPTY_CHILDREN = new Object[] {}; final List filters; final ModelWorkspace workspace; private boolean restrictedToModelResourcesOnly; /** * Construct an instance of ModelWorkspaceView. */ public ModelWorkspaceView() { super(); this.filters = new LinkedList(); this.workspace = ModelWorkspaceManager.getModelWorkspaceManager().getModelWorkspace(); CoreArgCheck.isNotNull(this.workspace); this.restrictedToModelResourcesOnly = DEFAULT_RESTRICT_TO_MODEL_RESOURCES_ONLY; } /** * Return whether only {@link ModelWorkspaceItem} instances will be shown in the view, or whether other {@link IResource} * instances will also be shown. Of course, if any of the {@link #getModelWorkspaceFilters()} filter out non-ModelResource * instances, then they will not be visible regardless of this setting. By default, only ModelWorkspaceItems are visible (this * method returns true). * * @return true if only ModelWorkspaceItem instances will be visible, or false if both ModelWorkspaceItems and other IResource * instances will be visible. * @see #setRestrictedToModelWorkspaceItemsOnly(boolean) */ public boolean isRestrictedToModelWorkspaceItemsOnly() { return restrictedToModelResourcesOnly; } /** * Set whether only {@link ModelWorkspaceItem} instances will be shown in the view, or whether other {@link IResource} * instances will also be shown. Of course, if any of the {@link #getModelWorkspaceFilters()} filter out non-ModelResource * instances, then they will not be visible regardless of this setting. * * @param b true if only ModelWorkspaceItem instances will be visible, or false if both ModelWorkspaceItems and other * IResource instances will be visible. * @see #isRestrictedToModelWorkspaceItemsOnly() */ public void setRestrictedToModelWorkspaceItemsOnly( final boolean b ) { restrictedToModelResourcesOnly = b; } /** * Return the list of {@link ModelWorkspaceFilter} instances used by this view. The returned list should be modified to add or * remove filters. However, the view does not make any special effort when accessing the filters, so care must be taken to not * modify this list at the same time the view is using the filters. * * @return the List of {@link ModelWorkspaceFilter} instances; never null */ public List getModelWorkspaceFilters() { return filters; } protected boolean isVisible( final Object parent, final Object object ) { final Iterator iter = this.filters.iterator(); while (iter.hasNext()) { final ModelWorkspaceFilter filter = (ModelWorkspaceFilter)iter.next(); if (filter.select(parent, object)) { return true; } } // no filter said the object was visible return false; } /** * Get the current path for the supplied object. * * @param object the object for which the path is to be determined; may not be null * @return the path for the supplied object; null if the path could not be found or determined for the supplied object */ public IPath getPath( final Object object ) { if (object instanceof ModelWorkspaceItem) { return ((ModelWorkspaceItem)object).getPath(); } if (object instanceof EObject) { final EObject eObject = (EObject)object; final ModelEditor editor = ModelerCore.getModelEditor(); // Find the model resource for the model object (the editor method checks for null) ... final ModelResource resource = editor.findModelResource(eObject); final IPath modelPath = resource.getPath(); final IPath pathInModel = editor.getModelRelativePath(eObject); return modelPath.append(pathInModel); } return null; } public Object findObject( final IPath path ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(path); // Loop over the segments in the path ... final String[] segments = path.segments(); Object object = this.workspace; for (int i = 0; i < segments.length; ++i) { final String segment = segments[i]; if (object instanceof ModelResource) { final ModelResource modelResource = (ModelResource)object; final IPath pathInModel = path.removeFirstSegments(i); final ModelEditor editor = ModelerCore.getModelEditor(); return editor.findObjectByPath(modelResource, pathInModel); } if (object instanceof ModelWorkspaceItem) { final ModelWorkspaceItem item = (ModelWorkspaceItem)object; object = item.getChild(segment); } } return object; } /** * Find the {@link ModelResource} that is represented by the supplied path or that contains the object with the specified * path. * * @param path the path; may not be null * @return the ModelResource, or null if the path does not reflect a ModelResource or an object within a ModelResource * @throws ModelWorkspaceException if there is an error in the ModelWorkspace */ public ModelResource findModelResourceForObject( final IPath path ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(path); // Loop over the segments in the path ... final String[] segments = path.segments(); Object object = this.workspace; for (int i = 0; i < segments.length; ++i) { final String segment = segments[i]; if (object instanceof ModelResource) { return (ModelResource)object; } if (object instanceof ModelWorkspaceItem) { final ModelWorkspaceItem item = (ModelWorkspaceItem)object; object = item.getChild(segment); } } return null; } /** * Returns the child elements of the given parent element. * * @param parentElement the parent element; may not be null * @return an array of child elements * @throws ModelWorkspaceException if there is an error obtaining the information */ public Object[] getChildren( final Object parent ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(parent); // -------------------------------------------------- // Compute the children of the supplied parent ... // -------------------------------------------------- final Object children = doGetChildren(parent); if (children == null) { return EMPTY_CHILDREN; } // -------------------------------------------------- // Remove objects the filters say are not visible ... // -------------------------------------------------- final List results = new LinkedList(); if (children instanceof Object[]) { final Object[] childObjects = (Object[])children; // The children are represented as an array boolean allChildren = true; for (int i = 0; i < childObjects.length; ++i) { final Object child = childObjects[i]; if (isVisible(parent, child)) { results.add(child); } else { allChildren = false; } } if (allChildren) { // Add the children are to be returned, so simply return the array return childObjects; } } else if (children instanceof Collection) { final Collection childrenList = (Collection)children; // The children are represented as a list final Iterator iter = childrenList.iterator(); while (iter.hasNext()) { final Object child = iter.next(); if (isVisible(parent, child)) { results.add(child); } } } // --------------------------------- // Convert to the required array ... // --------------------------------- return results.toArray(); } /** * Method that is called by {@link #getChildren(Object)} to actually compute all of the children for the supplied parent. The * filtering is not done by this method, but is instead done within the {@link #getChildren(Object)} method. * <p> * This method should be overridden to change the computation of the children for an object. However, changing which children * of an object are visible is accomplished by adding {@link #getModelWorkspaceFilters() filters}. * </p> * * @param parent the parent; never null (not checked in this method) * @return the children for the parent; either an Object[] or a Collection * @throws ModelWorkspaceException if there is an error obtaining the information */ protected Object doGetChildren( final Object parent ) throws ModelWorkspaceException { // First check whether eobject ... if (parent instanceof EObject) { return ((EObject)parent).eContents(); } // Then check whether model resource ... else if (parent instanceof ModelResource) { return ((ModelResource)parent).getEObjects(); } // Then check whether any model workspace item ... else if (parent instanceof ModelWorkspaceItem) { final ModelWorkspaceItem mwsItem = (ModelWorkspaceItem)parent; final ModelWorkspaceItem[] children = mwsItem.getChildren(); if (this.restrictedToModelResourcesOnly) { // Only want to show ModelWorkspaceItems return children; } // Find the non-model resources in the list ... final Set modelResources = new HashSet(); final List results = new ArrayList(); for (int i = 0; i < children.length; ++i) { final ModelWorkspaceItem item = children[i]; results.add(item); final IResource iresource = item.getCorrespondingResource(); if (iresource != null) { modelResources.add(iresource); } } try { final IResource iresource = mwsItem.getCorrespondingResource(); if (iresource != null && iresource instanceof IContainer) { final IContainer container = (IContainer)iresource; final IResource[] resourceChildren = container.members(); for (int i = 0; i < resourceChildren.length; ++i) { final IResource resource = resourceChildren[i]; if (!modelResources.contains(resource)) { results.add(resource); } } } } catch (ModelWorkspaceException e) { ModelerCore.Util.log(e); } catch (CoreException e) { ModelerCore.Util.log(e); } return results; } return null; } /** * Returns whether the given element has children. * <p> * Intended as an optimization for when the viewer does not need the actual children. Clients may be able to implement this * more efficiently than <code>getChildren</code>. * </p> * * @param element the element * @return <code>true</code> if the given element has children, and <code>false</code> if it has no children * @throws ModelWorkspaceException if there is an error obtaining the information */ public boolean hasChildren( final Object element ) throws ModelWorkspaceException { final Object children = doGetChildren(element); // Do the fast checks first ... if (children == EMPTY_CHILDREN) { return false; } if (children instanceof Object[]) { final Object[] childObjects = (Object[])children; for (int i = 0; i < childObjects.length; ++i) { final Object child = childObjects[i]; if (isVisible(element, child)) { return true; } } return false; } if (children instanceof Collection) { final Collection childrenList = (Collection)children; final Iterator iter = childrenList.iterator(); while (iter.hasNext()) { final Object child = iter.next(); if (isVisible(element, child)) { return true; } } return false; } return false; } /** * Returns the parent for the given element, or <code>null</code> indicating that the parent can't be computed. * * @param element the element; may not be null * @return the parent element, or <code>null</code> if it has none or if the parent cannot be computed * @throws ModelWorkspaceException if there is an error obtaining the information */ public Object getParent( final Object element ) { CoreArgCheck.isNotNull(element); if (element instanceof EObject) { final EObject obj = (EObject)element; final EObject parentObject = obj.eContainer(); if (parentObject != null) { return parentObject; } // There is no parent EObject, so return the ModelResource that contains this object ... return this.workspace.findModelResource(obj); } if (element instanceof ModelWorkspaceItem) { return ((ModelWorkspaceItem)element).getParent(); } return null; } }