| /******************************************************************************* |
| * Copyright (c) 2003, 2007 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.wst.common.componentcore.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.jobs.ILock; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.jem.util.UIContextDetermination; |
| import org.eclipse.jem.util.emf.workbench.ProjectUtilities; |
| import org.eclipse.wst.common.componentcore.IEditModelHandler; |
| import org.eclipse.wst.common.componentcore.ModuleCoreNature; |
| import org.eclipse.wst.common.componentcore.UnresolveableURIException; |
| import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil; |
| import org.eclipse.wst.common.componentcore.internal.impl.ResourceTreeNode; |
| import org.eclipse.wst.common.componentcore.internal.util.EclipseResourceAdapter; |
| import org.eclipse.wst.common.componentcore.resolvers.IReferenceResolver; |
| import org.eclipse.wst.common.componentcore.resolvers.ReferenceResolverUtil; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; |
| import org.eclipse.wst.common.componentcore.resources.IVirtualReference; |
| import org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil; |
| import org.eclipse.wst.common.internal.emfworkbench.edit.EMFWorkbenchEditContextFactory; |
| import org.eclipse.wst.common.internal.emfworkbench.validateedit.IValidateEditContext; |
| |
| /** |
| * <p> |
| * Provides a Facade pattern for accessing the Web Tools Platform EMF Module Model. ModuleCore can |
| * be used as a static utility or an instance adapter. |
| * </p> |
| * <p> |
| * ModuleCore hides the management of accessing EditModels ( |
| * {@see org.eclipse.wst.common.modulecore.ModuleStructuralModel}) correctly. Each project has |
| * exactly one ({@see org.eclipse.wst.common.modulecore.ModuleStructuralModel}) for read and |
| * exactly one for write. Each of these is shared among all clients and reference counted as |
| * necessary. Clients should use ModuleCore when working with the WTP Modules Structural Model. |
| * </p> |
| * |
| * <p> |
| * Each ModuleCore edit facade is designed to manage the EditModel lifecycle for clients. However, |
| * while each ModuleCore is designed to be passed around as needed, clients must enforce the |
| * ModuleCore lifecycle. The most common method of acquiring a ModuleCore edit facade is to use |
| * {@see #getModuleCoreForRead(IProject)} or {@see #getModuleCoreForWrite(IProject)}. |
| * </p> |
| * <p> |
| * When clients have concluded their use of their ModuleCore instance adapter , <b>clients must call |
| * {@see #dispose()}</b>. |
| * </p> |
| * <p> |
| * For more information about the underlying EditModel, see <a |
| * href="ModuleCoreNature.html#module-structural-model">the discussion of the ModuleStructuralModel |
| * </a>. |
| * <p> |
| * The following class is experimental until fully documented. |
| * </p> |
| * |
| * @see org.eclipse.wst.common.componentcore.ModuleCoreNature |
| * @see org.eclipse.wst.common.componentcore.internal.ModuleStructuralModel |
| */ |
| public class StructureEdit implements IEditModelHandler { |
| |
| public static final Class ADAPTER_TYPE = StructureEdit.class; |
| |
| public static String MODULE_META_FILE_NAME = ".settings/org.eclipse.wst.common.component"; //$NON-NLS-1$ |
| |
| private final static ComponentcoreFactory COMPONENT_FACTORY = ComponentcoreFactory.eINSTANCE; |
| private static final ComponentResource[] NO_RESOURCES = new ComponentResource[0]; |
| |
| private final ModuleStructuralModel structuralModel; |
| private final Map dependentCores = new HashMap(); |
| private IProject aProject; |
| private boolean isStructuralModelSelfManaged; |
| private boolean isReadOnly; |
| |
| private static final WorkbenchComponent[] NO_COMPONENTS = new WorkbenchComponent[0]; |
| |
| /** |
| * |
| * <p> |
| * Each ModuleCore edit facade is tied to a specific project. A project |
| * may have multiple ModuleCore edit facades live at any given time. |
| * </p> |
| * <p> |
| * Use to acquire a ModuleCore facade for a specific project that will not |
| * be used for editing. Invocations of any save*() API on an instance |
| * returned from This method will throw exceptions. |
| * </p> |
| * |
| * @param aProject |
| * The IProject that contains the WTP Modules model to load |
| * @return A ModuleCore edit facade to access the WTP Modules Model, null |
| * for non-flexible projects |
| */ |
| public static StructureEdit getStructureEditForRead(IProject aProject) { |
| ModuleCoreNature nature = ModuleCoreNature.getModuleCoreNature(aProject); |
| return nature != null ? new StructureEdit(nature, true) : null; |
| } |
| |
| /** |
| * |
| * <p> |
| * Each ModuleCore edit facade is tied to a specific project. A project may have multiple |
| * ModuleCore edit facades live at any given time. |
| * </p> |
| * <p> |
| * Use to acquire a ModuleCore facade for a specific project that may be used to modify the |
| * model. |
| * </p> |
| * |
| * @param aProject |
| * The IProject that contains the WTP Modules model to load |
| * @return A ModuleCore edit facade to access the WTP Modules Model |
| */ |
| public static StructureEdit getStructureEditForWrite(IProject aProject) { |
| ModuleCoreNature nature = ModuleCoreNature.getModuleCoreNature(aProject); |
| return nature != null ? new StructureEdit(nature, false) : null; |
| } |
| |
| /** |
| * <p> |
| * A convenience API to fetch the {@see ModuleCoreNature} for a particular module URI. The |
| * module URI must be of the valid form, or an exception will be thrown. The module URI must be |
| * contained by a project that has a {@see ModuleCoreNature} or null will be returned. |
| * </p> |
| * <p> |
| * <b>This method may return null. </b> |
| * </p> |
| * |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @return The ModuleCoreNature of the project associated with aModuleURI |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public static ModuleCoreNature getModuleCoreNature(URI aModuleURI) throws UnresolveableURIException { |
| IProject container = getContainingProject(aModuleURI); |
| if (container != null) |
| return ModuleCoreNature.getModuleCoreNature(container); |
| return null; |
| } |
| |
| /** |
| * <p> |
| * For {@see WorkbenchComponent}s that are contained within a project, the containing project |
| * can be determined with the {@see WorkbenchComponent}'s fully-qualified module URI. |
| * </p> |
| * <p> |
| * The following method will return the the corresponding project for the supplied module URI, |
| * if it can be determined. |
| * </p> |
| * <p> |
| * The method will not return an inaccessible project. |
| * </p> |
| * <p> |
| * <b>This method may return null. </b> |
| * </p> |
| * |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @return The project that contains the module referenced by the module URI |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public static IProject getContainingProject(WorkbenchComponent aComponent) { |
| IProject project = ProjectUtilities.getProject(aComponent); |
| if (project != null && project.isAccessible()) |
| return project; |
| return null; |
| } |
| |
| /** |
| * <p> |
| * For {@see WorkbenchComponent}s that are contained within a project, the containing project |
| * can be determined with the {@see WorkbenchComponent}'s fully-qualified module URI. |
| * </p> |
| * <p> |
| * The following method will return the the corresponding project for the supplied module URI, |
| * if it can be determined. |
| * </p> |
| * <p> |
| * The method will not return an inaccessible project. |
| * </p> |
| * <p> |
| * <b>This method may return null. </b> |
| * </p> |
| * |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @return The project that contains the module referenced by the module URI |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public static IProject getContainingProject(URI aModuleURI) throws UnresolveableURIException { |
| ModuleURIUtil.ensureValidFullyQualifiedModuleURI(aModuleURI); |
| String projectName = aModuleURI.segment(ModuleURIUtil.ModuleURI.PROJECT_NAME_INDX); |
| if (projectName == null || projectName.length() == 0) |
| throw new UnresolveableURIException(aModuleURI); |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
| if (project.isAccessible()) |
| return project; |
| return null; |
| } |
| |
| /** |
| * <p> |
| * Returns the corresponding Eclipse IResource, if it can be determined, for the given |
| * {@see ComponentResource}. The {@see ComponentResource#getSourcePath()} must return a |
| * valid resource path for This method to return a valid value. The returned value may be either |
| * an {@see org.eclipse.core.resources.IFile} or {@see org.eclipse.core.resources.IFolder}. |
| * A client may use the return value of {@see IResource#getType()} to determine what type |
| * of resource was returned. (@see IResource#FILE} or {@see IResource#FOLDER}). |
| * </p> |
| * <p> |
| * <b>This method may return null. </b> |
| * </p> |
| * |
| * @param aModuleResource |
| * A ComponentResource with a valid sourcePath |
| * @return The corresponding Eclipse IResource, if available. |
| */ |
| public static IResource getEclipseResource(ComponentResource aModuleResource) { |
| EclipseResourceAdapter eclipseResourceAdapter = (EclipseResourceAdapter) ExtendedEcoreUtil.getAdapter(aModuleResource,aModuleResource.eAdapters(), EclipseResourceAdapter.ADAPTER_TYPE); |
| if (eclipseResourceAdapter != null) |
| return eclipseResourceAdapter.getEclipseResource(); |
| eclipseResourceAdapter = new EclipseResourceAdapter(); |
| eclipseResourceAdapter.setTarget(aModuleResource); |
| aModuleResource.eAdapters().add(eclipseResourceAdapter); |
| return eclipseResourceAdapter.getEclipseResource(); |
| } |
| |
| /** |
| * <p> |
| * Parses the supplied URI for the deployed name name of the {@see WorkbenchComponent} referenced |
| * by the URI. |
| * </p> |
| * |
| * @param aFullyQualifiedModuleURI |
| * A valid, fully-qualified module URI |
| * @return The deployed name of the referenced {@see WorkbenchComponent} |
| * @throws UnresolveableURIException |
| * If the supplied URI is invalid or unresolveable |
| */ |
| public static String getDeployedName(URI aFullyQualifiedModuleURI) throws UnresolveableURIException { |
| return ModuleURIUtil.getDeployedName(aFullyQualifiedModuleURI); |
| } |
| |
| //public static ComponentType getComponentType(IVirtualContainer aComponent) { |
| public static ComponentType getComponentType(IVirtualComponent aComponent) { |
| StructureEdit componentCore = null; |
| ComponentType componentType = null; |
| try { |
| componentCore = StructureEdit.getStructureEditForRead(aComponent.getProject()); |
| WorkbenchComponent wbComponent = componentCore.getComponent(); |
| componentType = wbComponent.getComponentType(); |
| } finally { |
| if (componentCore != null) |
| componentCore.dispose(); |
| } |
| return componentType; |
| } |
| |
| public static IVirtualReference createVirtualReference(IVirtualComponent context, ReferencedComponent reference) { |
| IReferenceResolver resolver = ReferenceResolverUtil.getDefault().getResolver(context, reference); |
| return resolver.resolve(context, reference); |
| } |
| |
| protected StructureEdit(ModuleCoreNature aNature, boolean toAccessAsReadOnly) { |
| // always get the write editmodel - one instance only |
| structuralModel = aNature.getModuleStructuralModelForWrite(this); |
| aProject = aNature.getProject(); |
| isReadOnly = toAccessAsReadOnly; |
| isStructuralModelSelfManaged = true; |
| } |
| |
| /** |
| * <p> |
| * The following constructor is used to manage an already loaded model. Clients should use the |
| * following line if they intend to use this constructor: <br> |
| * <br> |
| * <code>ModuleCore componentCore = (ModuleCore) aStructuralModel.getAdapter(ModuleCore.ADAPTER_TYPE)</code>. |
| * </p> |
| * |
| * @param aStructuralModel |
| * The edit model to be managed by this ModuleCore |
| */ |
| public StructureEdit(ModuleStructuralModel aStructuralModel) { |
| structuralModel = aStructuralModel; |
| aProject = aStructuralModel.getProject(); |
| } |
| |
| /** |
| * <p> |
| * Force a save of the underlying model. The following method should be used with care. Unless |
| * required, use {@see #saveIfNecessary(IProgressMonitor) instead. |
| * </p> |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.wst.common.componentcore.IEditModelHandler#save() |
| * @throws IllegalStateException |
| * If the ModuleCore object was created as read-only |
| */ |
| public void save(IProgressMonitor aMonitor) { |
| if (isReadOnly) |
| throwAttemptedReadOnlyModification(); |
| else if (validateEdit().isOK()) { |
| // Make sure we obtain workspace rule before saving |
| IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
| try { |
| //OK wait to get workspace root before refreshing |
| Job.getJobManager().beginRule(root, null); |
| synchronized (structuralModel) { |
| if (!structuralModel.isDisposed()) |
| structuralModel.save(aMonitor, this); |
| } |
| } finally { |
| Job.getJobManager().endRule(root); |
| } |
| } |
| } |
| |
| /** |
| * <p> |
| * Save the underlying model only if no other clients are currently using the model. If the |
| * model is not shared, it will be saved. If it is shared, the save will be deferred. |
| * </p> |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.wst.common.componentcore.IEditModelHandler#saveIfNecessary() |
| * @throws IllegalStateException |
| * If the ModuleCore object was created as read-only |
| */ |
| public void saveIfNecessary(IProgressMonitor aMonitor) { |
| if (isReadOnly) |
| throwAttemptedReadOnlyModification(); |
| else if (structuralModel.isDirty() && validateEdit().isOK()) { |
| if (!structuralModel.isDisposed()) |
| structuralModel.saveIfNecessary(aMonitor, this); |
| } |
| } |
| |
| /** |
| * <p> |
| * Clients must call the following method when they have finished using the model, even if the |
| * ModuleCore edit facade was created as read-only. |
| * </p> |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.wst.common.componentcore.IEditModelHandler#dispose() |
| */ |
| public void dispose() { |
| if (isStructuralModelSelfManaged && structuralModel!=null) { |
| synchronized (structuralModel) { |
| if (!structuralModel.isDisposed()) |
| structuralModel.releaseAccess(this); |
| } |
| } |
| if (dependentCores!=null && dependentCores.size() > 0) { |
| synchronized (dependentCores) { |
| for (Iterator cores = dependentCores.values().iterator(); cores.hasNext();) { |
| StructureEdit core = (StructureEdit) cores.next(); |
| if (core != null) |
| core.dispose(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * <p> |
| * Creates a default WTP Module Structural Metamodel file if necessary. |
| * </p> |
| */ |
| public void prepareProjectComponentsIfNecessary() { |
| |
| synchronized (structuralModel) { |
| if (!structuralModel.isDisposed()) { |
| try { |
| structuralModel.prepareProjectModulesIfNecessary(); |
| } catch (CoreException e) { |
| ModulecorePlugin.logError(e); |
| } |
| } |
| } |
| } |
| |
| /** |
| * <p> |
| * When loaded for write, the current ModuleCore may return the root object, which can be used |
| * to add or remove {@see WorkbenchComponent}s. If a client needs to just read the existing |
| * {@see WorkbenchComponent}s, use {@see #getWorkbenchModules()}. |
| * </p> |
| * <p> |
| * Deadlock Warning: Calling this method requires two locks. First the component file's file lock |
| * is required and then the EMFWorkbenchEditContextFactory's projectILock is required. If another |
| * thread acquires these same two locks in the opposite order, deadlock could occur. |
| * </p> |
| * |
| * @return The root object of the underlying model |
| */ |
| public ProjectComponents getComponentModelRoot() { |
| IFile file = structuralModel.getComponentFile(); |
| if (file == null) return null; |
| ProjectComponents comps = null; |
| ILock lock = EMFWorkbenchEditContextFactory.getProjectLockObject(structuralModel.getProject()); |
| try{ |
| if(null != lock){ |
| lock.acquire(); |
| } |
| synchronized(structuralModel){ |
| if (!structuralModel.isDisposed()) |
| comps = (ProjectComponents) structuralModel.getPrimaryRootObject(); |
| } |
| } finally{ |
| if(null != lock){ |
| lock.release(); |
| } |
| } |
| return comps; |
| } |
| |
| /** |
| * <p> |
| * Return the an array of ComponentResource which basically represent the source containers of a |
| * WorkbenchResource. |
| * <p> |
| * |
| * @param component |
| * @return |
| */ |
| public ComponentResource[] getSourceContainers(WorkbenchComponent component) { |
| // TODO Api in progress: Need to return the Java Source containers of the project |
| // TODO MDE: I don't know if I agree with the placement of this method. |
| return null; |
| } |
| |
| /** |
| * <p> |
| * Clients that wish to modify the individual {@see WorkbenchComponent} instances may use |
| * this method. If clients need to add or remove {@see WorkbenchComponent} instances, use |
| * {@see #getProjectModules()} to get the root object and then access the contained |
| * {@see WorkbenchComponent}s through {@see ProjectComponents#getWorkbenchModules()}. |
| * |
| * @return The WorkbenchModules of the underlying model, if any. |
| */ |
| public WorkbenchComponent[] getWorkbenchModules() { |
| ProjectComponents pc = getComponentModelRoot(); |
| if(pc != null) { |
| List wbModules = pc.getComponents(); |
| return (WorkbenchComponent[]) wbModules.toArray(new WorkbenchComponent[wbModules.size()]); |
| } |
| return NO_COMPONENTS; |
| } |
| |
| /** |
| * <p> |
| * Create a {@see WorkbenchComponent} with the given deployed name. The returned module |
| * will be contained by the root object of the current ModuleCore (so no need to re-add it to |
| * the Module Module root object). The current ModuleCore must not be read-only to invoke This |
| * method. |
| * </p> |
| * |
| * @param aDeployName |
| * A non-null String that will be assigned as the deployed-name |
| * @return A {@see WorkbenchComponent}associated with the current ModuleCore with the supplied |
| * deployed name |
| * @throws IllegalStateException |
| * If the current ModuleCore was created as read-only |
| */ |
| public WorkbenchComponent createWorkbenchModule(String aDeployName) { |
| if (isReadOnly) |
| throwAttemptedReadOnlyModification(); |
| WorkbenchComponent module = COMPONENT_FACTORY.createWorkbenchComponent(); |
| module.setName(aDeployName); |
| getComponentModelRoot().getComponents().add(module); |
| return module; |
| } |
| |
| /** |
| * <p> |
| * Create a {@see ComponentResource} with the sourcePath of aResource. The current |
| * ModuleCore must not be read-only to invoke This method. |
| * </p> |
| * |
| * @param aModule |
| * A non-null {@see WorkbenchComponent}to contain the created |
| * {@see ComponentResource} |
| * @param aResource |
| * A non-null IResource that will be used to set the sourcePath |
| * @return A {@see ComponentResource}associated with the current ModuleCore with its sourcePath |
| * equivalent to aResource |
| * @throws IllegalStateException |
| * If the current ModuleCore was created as read-only |
| */ |
| public ComponentResource createWorkbenchModuleResource(IResource aResource) { |
| if (isReadOnly) |
| throwAttemptedReadOnlyModification(); |
| |
| ComponentResource moduleResource = COMPONENT_FACTORY.createComponentResource(); |
| moduleResource.setSourcePath(aResource.getProjectRelativePath().makeAbsolute()); |
| return moduleResource; |
| } |
| |
| /** |
| * <p> |
| * Create a {@see ComponentType} with the sourcePath of aResource. The returned resource |
| * will be associated with the current ModuleCore. The current ModuleCore must not be read-only |
| * to invoke This method. |
| * </p> |
| * |
| * @param aResource |
| * A non-null IResource that will be used to set the sourcePath |
| * @return A {@see ComponentResource}associated with the current ModuleCore with its sourcePath |
| * equivalent to aResource |
| * @throws IllegalStateException |
| * If the current ModuleCore was created as read-only |
| */ |
| public ComponentType createModuleType(String aModuleTypeId) { |
| if (isReadOnly) |
| throwAttemptedReadOnlyModification(); |
| |
| ComponentType moduleType = COMPONENT_FACTORY.createComponentType(); |
| moduleType.setComponentTypeId(aModuleTypeId); |
| return moduleType; |
| } |
| |
| /** |
| * <p> |
| * Search the given module (indicated by aModuleURI) for the {@see ComponentResource}s |
| * identified by the module-relative path (indicated by aDeployedResourcePath). |
| * </p> |
| * @deprecated To be removed at next Integration Build 04/14/05 MDE. No substitute. (No clients). |
| * |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @param aDeployedResourcePath |
| * A module-relative path to a deployed file |
| * @return An array of WorkbenchModuleResources that contain the URI specified by the |
| * module-relative aDeployedResourcePath |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public ComponentResource[] findResourcesByRuntimePath(URI aModuleURI, URI aDeployedResourcePath) throws UnresolveableURIException { |
| WorkbenchComponent module = getComponent(); |
| return module.findResourcesByRuntimePath(new Path(aDeployedResourcePath.path())); |
| } |
| |
| /** |
| * <p> |
| * Search the the module (indicated by the root of aModuleResourcePath) for the |
| * {@see ComponentResource}s identified by the module-qualified path (indicated by |
| * aDeployedResourcePath). |
| * </p> |
| * @deprecated To be removed at next Integration Build 04/14/05 MDE Use IPath Signature instead. |
| * |
| * @param aModuleResourcePath |
| * A valid fully-qualified URI of a deployed resource within a specific |
| * WorkbenchComponent |
| * @return An array of WorkbenchModuleResources that contain the URI specified by |
| * aModuleResourcePath |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public ComponentResource[] findResourcesByRuntimePath(URI aModuleResourcePath) throws UnresolveableURIException { |
| |
| URI deployedURI = ModuleURIUtil.trimToDeployPathSegment(aModuleResourcePath); |
| IPath deployedPath = new Path(deployedURI.path()); |
| return findResourcesByRuntimePath(ModuleURIUtil.getDeployedName(aModuleResourcePath), deployedPath); |
| } |
| |
| /** |
| * <p> |
| * Search the the module (indicated by the root of aModuleResourcePath) for the |
| * {@see ComponentResource}s identified by the module-qualified path (indicated by |
| * aDeployedResourcePath). |
| * </p> |
| * |
| * @param aModuleResourcePath |
| * A valid fully-qualified URI of a deployed resource within a specific |
| * WorkbenchComponent |
| * @return An array of WorkbenchModuleResources that contain the URI specified by |
| * aModuleResourcePath |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public ComponentResource[] findResourcesByRuntimePath(String aModuleName, IPath aModuleResourcePath) { |
| WorkbenchComponent module = getComponent(); |
| return module.findResourcesByRuntimePath(aModuleResourcePath); |
| } |
| public ComponentResource[] findResourcesBySourcePath(URI aWorkspaceRelativePath) throws UnresolveableURIException { |
| return findResourcesBySourcePath(aWorkspaceRelativePath,ResourceTreeNode.CREATE_NONE); |
| } |
| /** |
| * <p> |
| * Locates the {@see ComponentResource}s that contain the supplied resource in their source |
| * path. There are no representations about the containment of the {@see ComponentResource}s |
| * which are returned. The only guarantee is that the returned elements are contained within the |
| * same project. |
| * </p> |
| * <p> |
| * The sourcePath of each {@see ComponentResource} will be mapped to either an IFile or an |
| * IFolder. As a result, if the {@see ComponentResource} is a container mapping, the path |
| * of the supplied resource may not be identical the sourcePath of the {@see ComponentResource}. |
| * </p> |
| * @deprecated To be removed at next Integration Build 04/14/05 MDE Use IPath Signature instead. |
| * |
| * @param aWorkspaceRelativePath |
| * A valid fully-qualified workspace-relative path of a given resource |
| * @return An array of WorkbenchModuleResources which have sourcePaths that contain the given |
| * resource |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public ComponentResource[] findResourcesBySourcePath(URI aWorkspaceRelativePath, int resourceFlag) throws UnresolveableURIException { |
| return findResourcesBySourcePath(new Path(aWorkspaceRelativePath.path()),resourceFlag); |
| } |
| public ComponentResource[] findResourcesBySourcePath(IPath aProjectRelativePath) throws UnresolveableURIException { |
| return findResourcesBySourcePath(aProjectRelativePath,ResourceTreeNode.CREATE_NONE); |
| } |
| /** |
| * <p> |
| * Locates the {@see WorkbenchComponent}s that contains the resource with the given source |
| * path. There are no representations about the containment of the {@see ComponentResource}s |
| * which are returned. The only guarantee is that the returned elements are contained within the |
| * same project. |
| * </p> |
| * <p> |
| * The sourcePath of each {@see ComponentResource} will be mapped to either an IFile or an |
| * IFolder. As a result, if the {@see ComponentResource} is a container mapping, the path |
| * of the supplied resource may not be identical the sourcePath of the {@see ComponentResource}. |
| * </p> |
| * |
| * @param aProjectRelativePath |
| * A valid project-relative path of a given resource |
| * resourceFlag |
| * A bit flag that determines if Resources should be created during the search |
| * CREATE_NONE |
| * CREATE_RESOURCE_ALWAYS |
| * CREATE_TREENODE_IFNEC |
| * @return An array of WorkbenchModuleResources which have sourcePaths that contain the given |
| * resource |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public WorkbenchComponent findComponent(IPath aProjectRelativeResourcePath, int resourceFlag) throws UnresolveableURIException { |
| ProjectComponents projectModules = getComponentModelRoot(); |
| if (projectModules == null) return null; |
| EList modules = projectModules.getComponents(); |
| |
| WorkbenchComponent module = null; |
| boolean resourceExists = false; |
| for (int i = 0; i < modules.size(); i++) { |
| module = (WorkbenchComponent) modules.get(i); |
| resourceExists = module.exists(aProjectRelativeResourcePath,resourceFlag); |
| if (!resourceExists && aProjectRelativeResourcePath.segments().length > 1) { |
| resourceExists = module.exists(aProjectRelativeResourcePath.removeFirstSegments(1),resourceFlag); |
| } |
| if (resourceExists) |
| return module; |
| } |
| return null; |
| } |
| /** |
| * <p> |
| * Locates the {@see ComponentResource}s that contain the supplied resource in their source |
| * path. There are no representations about the containment of the {@see ComponentResource}s |
| * which are returned. The only guarantee is that the returned elements are contained within the |
| * same project. |
| * </p> |
| * <p> |
| * The sourcePath of each {@see ComponentResource} will be mapped to either an IFile or an |
| * IFolder. As a result, if the {@see ComponentResource} is a container mapping, the path |
| * of the supplied resource may not be identical the sourcePath of the {@see ComponentResource}. |
| * </p> |
| * |
| * @param aProjectRelativePath |
| * A valid project-relative path of a given resource |
| * resourceFlag |
| * A bit flag that determines if Resources should be created during the search |
| * CREATE_NONE |
| * CREATE_RESOURCE_ALWAYS |
| * CREATE_TREENODE_IFNEC |
| * @return An array of WorkbenchModuleResources which have sourcePaths that contain the given |
| * resource |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| public ComponentResource[] findResourcesBySourcePath(IPath aProjectRelativePath, int resourceFlag) throws UnresolveableURIException { |
| ProjectComponents projectModules = getComponentModelRoot(); |
| if (projectModules==null) |
| return NO_RESOURCES; |
| EList modules = projectModules.getComponents(); |
| |
| WorkbenchComponent module = null; |
| ComponentResource[] resources = null; |
| List foundResources = new ArrayList(); |
| for (int i = 0; i < modules.size(); i++) { |
| module = (WorkbenchComponent) modules.get(i); |
| resources = module.findResourcesBySourcePath(aProjectRelativePath,resourceFlag); |
| if (resources != null && resources.length != 0) |
| foundResources.addAll(Arrays.asList(resources)); |
| else if (aProjectRelativePath.segments().length > 1) { |
| resources = module.findResourcesBySourcePath(aProjectRelativePath.removeFirstSegments(1),resourceFlag); |
| if (resources != null && resources.length != 0) |
| foundResources.addAll(Arrays.asList(resources)); |
| } |
| } |
| if (foundResources.size() > 0) |
| return (ComponentResource[]) foundResources.toArray(new ComponentResource[foundResources.size()]); |
| return NO_RESOURCES; |
| } |
| |
| /** |
| * <p> |
| * Returns the {@see WorkbenchComponent} contained by the current ModuleCore with the |
| * deploy name aModuleName. |
| * </p> |
| * <p> |
| * <b>This method may return null. </b> |
| * </p> |
| * |
| * @param aModuleName |
| * @return The {@see WorkbenchComponent}contained by the current ModuleCore with the deploy |
| * name aModuleName |
| * @see WorkbenchComponent#getDeployedName() |
| * @deprecated - Use getComponent() - Only one component per project |
| */ |
| public WorkbenchComponent findComponentByName(String aModuleName) { |
| return getComponentModelRoot() != null ? getComponentModelRoot().findWorkbenchModule(aModuleName) : null; |
| } |
| |
| /** |
| * <p> |
| * Locate and return the {@see WorkbenchComponent} referenced by the fully-qualified |
| * aModuleURI. The method will work correctly even if the requested {@see WorkbenchComponent} |
| * is contained by another project. |
| * </p> |
| * |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @return The {@see WorkbenchComponent}referenced by aModuleURI |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| * @see WorkbenchComponent#getHandle() |
| */ |
| public WorkbenchComponent findComponentByURI(URI aModuleURI) throws UnresolveableURIException { |
| if (aModuleURI == null) |
| return null; |
| if(aModuleURI.scheme() == null && aModuleURI.segmentCount() == 1) |
| return getComponent(); |
| ModuleURIUtil.ensureValidFullyQualifiedModuleURI(aModuleURI); |
| String projectName = aModuleURI.segment(ModuleURIUtil.ModuleURI.PROJECT_NAME_INDX); |
| /* Accessing a local module */ |
| if (getProject()!=null && getProject().getName().equals(projectName)) |
| return getComponent(); |
| StructureEdit dependentCore = getDependentModuleCore(aModuleURI); |
| if (dependentCore != null) |
| return dependentCore.getComponent(); |
| return null; |
| } |
| |
| /** |
| * <p> |
| * Searches the available {@see WorkbenchComponent}s as available through |
| * {@see #getWorkbenchModules()} for {@see WorkbenchComponent}s that have a |
| * {@see WorkbenchComponent#getModuleType()}with a a module type Id as specified by |
| * aModuleTypeId. |
| * </p> |
| * |
| * @param aModuleTypeId |
| * A non-null module type id ({@see ComponentType#getModuleTypeId()}) |
| * @return A non-null array of the {@see WorkbenchComponent}s that match the given module type |
| * id |
| */ |
| // public WorkbenchComponent[] findComponentsByType(String aModuleTypeId) { |
| // WorkbenchComponent[] availableModules = getWorkbenchModules(); |
| // ComponentType moduleType; |
| // List results = new ArrayList(); |
| // for (int i = 0; i < availableModules.length; i++) { |
| // moduleType = availableModules[i].getComponentType(); |
| // if (moduleType != null && aModuleTypeId.equals(moduleType.getComponentTypeId())) |
| // results.add(availableModules[i]); |
| // } |
| // if (results.size() == 0) |
| // return NO_MODULES; |
| // return (WorkbenchComponent[]) results.toArray(new WorkbenchComponent[results.size()]); |
| // } |
| |
| /** |
| * Find and return the ReferencedComponent that represents the depedency from aComponent to aReferencedComponent. |
| * <p>This method could return null.</p> |
| * @param aComponent |
| * @param aReferencedComponent |
| * @return |
| */ |
| public ReferencedComponent findReferencedComponent(WorkbenchComponent aComponent, WorkbenchComponent aReferencedComponent) { |
| if(aComponent == null || aReferencedComponent == null) |
| return null; |
| |
| IProject referencedProject = getContainingProject(aReferencedComponent); |
| EList referencedComponents = aComponent.getReferencedComponents(); |
| String dependentProjectName = null; |
| for (Iterator iter = referencedComponents.iterator(); iter.hasNext();) { |
| ReferencedComponent referencedComponent = (ReferencedComponent) iter.next(); |
| dependentProjectName = referencedComponent.getHandle().segment(ModuleURIUtil.ModuleURI.PROJECT_NAME_INDX); |
| if(referencedProject.getName().equals(dependentProjectName)) |
| return referencedComponent; |
| |
| } |
| return null; |
| } |
| |
| /** |
| * <p> |
| * Returns true if the {@see ReferencedComponent} references a {@see WorkbenchComponent}( |
| * {@see ReferencedComponent#getHandle()}) which is contained by the project that the current |
| * ModuleCore is managing. The following method will determine if the dependency can be |
| * satisfied by the current project. |
| * </p> |
| * |
| * @param aDependentModule |
| * @return True if the {@see ReferencedComponent}references a {@see WorkbenchComponent}managed |
| * directly by the current ModuleCore |
| */ |
| public boolean isLocalDependency(ReferencedComponent aDependentModule) { |
| if (aDependentModule == null || aDependentModule.getHandle()==null) |
| return false; |
| URI dependentHandle = aDependentModule.getHandle(); |
| // with no scheme and a simple name, the referenced component must be local |
| if(dependentHandle.scheme() == null && dependentHandle.segmentCount() == 1) |
| return true; |
| try { |
| |
| String localProjectName = getProject().getName(); |
| if(ModuleURIUtil.ensureValidFullyQualifiedModuleURI(dependentHandle, false)) { |
| String dependentProjectName = aDependentModule.getHandle().segment(ModuleURIUtil.ModuleURI.PROJECT_NAME_INDX); |
| return localProjectName.equals(dependentProjectName); |
| } |
| } catch (UnresolveableURIException e) { |
| // Ignore |
| } |
| return false; |
| } |
| |
| /** |
| * @param aModuleURI |
| * A valid, fully-qualified module URI |
| * @return The ModuleCore facade for the supplied URI |
| * @throws UnresolveableURIException |
| * If the supplied module URI is invalid or unresolveable. |
| */ |
| private StructureEdit getDependentModuleCore(URI aModuleURI) throws UnresolveableURIException { |
| StructureEdit dependentCore = (StructureEdit) dependentCores.get(aModuleURI); |
| if (dependentCore != null) |
| return dependentCore; |
| synchronized (dependentCores) { |
| dependentCore = (StructureEdit) dependentCores.get(aModuleURI); |
| if (dependentCore == null) { |
| IProject container = getContainingProject(aModuleURI); |
| if (container != null) { |
| dependentCore = getStructureEditForRead(container); |
| dependentCores.put(aModuleURI, dependentCore); |
| } else |
| throw new UnresolveableURIException(aModuleURI); |
| } |
| } |
| return dependentCore; |
| } |
| |
| private void throwAttemptedReadOnlyModification() { |
| throw new IllegalStateException("Attempt to modify a ModuleCore edit facade that was loaded as read-only."); |
| } |
| |
| /** |
| * temporary method to return first module in the project |
| * |
| * @return first module in the project |
| * @deprecated |
| */ |
| public WorkbenchComponent getFirstModule() { |
| return getComponent(); |
| } |
| /** |
| * returns the one and only component in the project |
| * |
| * @return the component in the project if exists or null |
| * |
| */ |
| public WorkbenchComponent getComponent() { |
| WorkbenchComponent[] comps = getWorkbenchModules(); |
| if (comps.length > 0) |
| return comps[0]; |
| return null; |
| } |
| |
| public static URI createComponentURI(IProject aContainingProject, String aComponentName) { |
| return ModuleURIUtil.fullyQualifyURI(aContainingProject, aComponentName); |
| } |
| |
| protected IProject getProject() { |
| return aProject; |
| } |
| |
| public ModuleStructuralModel getModuleStructuralModel() { |
| return structuralModel; |
| } |
| |
| /** |
| * Validate edit for resource state |
| */ |
| protected IStatus validateEdit() { |
| IValidateEditContext validator = (IValidateEditContext) UIContextDetermination.createInstance(IValidateEditContext.CLASS_KEY); |
| return validator.validateState(getModuleStructuralModel()); |
| } |
| } |