| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.model; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceVisitor; |
| import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; |
| import org.eclipse.core.resources.mapping.ResourceMapping; |
| import org.eclipse.core.resources.mapping.ResourceMappingContext; |
| import org.eclipse.core.resources.mapping.ResourceTraversal; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IProjectFragment; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.IScriptModel; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.internal.ui.browsing.LogicalPackage; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| |
| /** |
| * An abstract super class to describe mappings from a model element to a set of |
| * resources. The class also provides factory methods to create resource |
| * mappings. |
| * |
| */ |
| public abstract class DLTKElementResourceMapping extends ResourceMapping { |
| |
| protected DLTKElementResourceMapping() { |
| } |
| |
| public IModelElement getModelElement() { |
| Object o = getModelObject(); |
| if (o instanceof IModelElement) |
| return (IModelElement) o; |
| return null; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (!(obj instanceof DLTKElementResourceMapping)) |
| return false; |
| return getModelElement() |
| .equals(((DLTKElementResourceMapping) obj).getModelElement()); |
| } |
| |
| @Override |
| public int hashCode() { |
| IModelElement modelElement = getModelElement(); |
| if (modelElement == null) |
| return super.hashCode(); |
| |
| return modelElement.hashCode(); |
| } |
| |
| @Override |
| public String getModelProviderId() { |
| return ScriptModelProvider.DLTK_MODEL_PROVIDER_ID; |
| } |
| |
| @Override |
| public boolean contains(ResourceMapping mapping) { |
| if (mapping instanceof DLTKElementResourceMapping) { |
| DLTKElementResourceMapping javaMapping = (DLTKElementResourceMapping) mapping; |
| IModelElement element = getModelElement(); |
| IModelElement other = javaMapping.getModelElement(); |
| if (other != null && element != null) |
| return element.getPath().isPrefixOf(other.getPath()); |
| } |
| return false; |
| } |
| |
| // ---- the factory code |
| // --------------------------------------------------------------- |
| |
| private static final class ScriptModelResourceMapping |
| extends DLTKElementResourceMapping { |
| private final IScriptModel fModel; |
| |
| private ScriptModelResourceMapping(IScriptModel model) { |
| Assert.isNotNull(model); |
| fModel = model; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fModel; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| IScriptProject[] projects = null; |
| try { |
| projects = fModel.getScriptProjects(); |
| } catch (ModelException e) { |
| DLTKUIPlugin.log(e); |
| return new IProject[0]; |
| } |
| IProject[] result = new IProject[projects.length]; |
| for (int i = 0; i < projects.length; i++) { |
| result[i] = projects[i].getProject(); |
| } |
| return result; |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| IScriptProject[] projects = fModel.getScriptProjects(); |
| ResourceTraversal[] result = new ResourceTraversal[projects.length]; |
| for (int i = 0; i < projects.length; i++) { |
| result[i] = new ResourceTraversal( |
| new IResource[] { projects[i].getProject() }, |
| IResource.DEPTH_INFINITE, 0); |
| } |
| return result; |
| } |
| } |
| |
| private static final class ScriptProjectResourceMapping |
| extends DLTKElementResourceMapping { |
| private final IScriptProject fProject; |
| |
| private ScriptProjectResourceMapping(IScriptProject project) { |
| Assert.isNotNull(project); |
| fProject = project; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fProject; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| return new IProject[] { fProject.getProject() }; |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| return new ResourceTraversal[] { new ResourceTraversal( |
| new IResource[] { fProject.getProject() }, |
| IResource.DEPTH_INFINITE, 0) }; |
| } |
| } |
| |
| private static final class PackageFragementRootResourceMapping |
| extends DLTKElementResourceMapping { |
| private final IProjectFragment fRoot; |
| |
| private PackageFragementRootResourceMapping(IProjectFragment root) { |
| Assert.isNotNull(root); |
| fRoot = root; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fRoot; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| return new IProject[] { fRoot.getScriptProject().getProject() }; |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| return new ResourceTraversal[] { new ResourceTraversal( |
| new IResource[] { fRoot.getResource() }, |
| IResource.DEPTH_INFINITE, 0) }; |
| } |
| } |
| |
| private static final class LocalPackageFragementTraversal |
| extends ResourceTraversal { |
| private final IScriptFolder fPack; |
| |
| public LocalPackageFragementTraversal(IScriptFolder pack) |
| throws CoreException { |
| super(new IResource[] { pack.getResource() }, IResource.DEPTH_ONE, |
| 0); |
| fPack = pack; |
| } |
| |
| @Override |
| public void accept(IResourceVisitor visitor) throws CoreException { |
| IFile[] files = getPackageContent(fPack); |
| final IResource resource = fPack.getResource(); |
| if (resource != null) |
| visitor.visit(resource); |
| for (int i = 0; i < files.length; i++) { |
| visitor.visit(files[i]); |
| } |
| } |
| } |
| |
| private static final class ScriptFolderResourceMapping |
| extends DLTKElementResourceMapping { |
| private final IScriptFolder fPack; |
| |
| private ScriptFolderResourceMapping(IScriptFolder pack) { |
| Assert.isNotNull(pack); |
| fPack = pack; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fPack; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| return new IProject[] { fPack.getScriptProject().getProject() }; |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| if (context instanceof RemoteResourceMappingContext) { |
| return new ResourceTraversal[] { new ResourceTraversal( |
| new IResource[] { fPack.getResource() }, |
| IResource.DEPTH_ONE, 0) }; |
| } else if (fPack.getResource() != null) { |
| return new ResourceTraversal[] { |
| new LocalPackageFragementTraversal(fPack) }; |
| } else { |
| return new ResourceTraversal[0]; |
| } |
| } |
| |
| @Override |
| public void accept(ResourceMappingContext context, |
| IResourceVisitor visitor, IProgressMonitor monitor) |
| throws CoreException { |
| if (context instanceof RemoteResourceMappingContext) { |
| super.accept(context, visitor, monitor); |
| } else { |
| // We assume a local context. |
| IFile[] files = getPackageContent(fPack); |
| if (monitor == null) |
| monitor = new NullProgressMonitor(); |
| monitor.beginTask("", files.length + 1); //$NON-NLS-1$ |
| final IResource resource = fPack.getResource(); |
| if (resource != null) |
| visitor.visit(resource); |
| monitor.worked(1); |
| for (int i = 0; i < files.length; i++) { |
| visitor.visit(files[i]); |
| monitor.worked(1); |
| } |
| } |
| } |
| } |
| |
| private static IFile[] getPackageContent(IScriptFolder pack) |
| throws CoreException { |
| List<IFile> result = new ArrayList<>(); |
| IContainer container = (IContainer) pack.getResource(); |
| if (container != null) { |
| IResource[] members = container.members(); |
| for (int m = 0; m < members.length; m++) { |
| IResource member = members[m]; |
| if (member instanceof IFile) { |
| IFile file = (IFile) member; |
| if ("class".equals(file.getFileExtension()) //$NON-NLS-1$ |
| && file.isDerived()) |
| continue; |
| result.add((IFile) member); |
| } |
| } |
| } |
| return result.toArray(new IFile[result.size()]); |
| } |
| |
| private static final class SourceModuleResourceMapping |
| extends DLTKElementResourceMapping { |
| private final ISourceModule fUnit; |
| |
| private SourceModuleResourceMapping(ISourceModule unit) { |
| Assert.isNotNull(unit); |
| fUnit = unit; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fUnit; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| return new IProject[] { fUnit.getScriptProject().getProject() }; |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| return new ResourceTraversal[] { new ResourceTraversal( |
| new IResource[] { fUnit.getResource() }, |
| IResource.DEPTH_ONE, 0) }; |
| } |
| } |
| |
| private static final class LogicalPackageResourceMapping |
| extends ResourceMapping { |
| private final IScriptFolder[] fFragments; |
| |
| private LogicalPackageResourceMapping(IScriptFolder[] fragments) { |
| fFragments = fragments; |
| } |
| |
| @Override |
| public Object getModelObject() { |
| return fFragments; |
| } |
| |
| @Override |
| public IProject[] getProjects() { |
| Set<IProject> result = new HashSet<>(); |
| for (int i = 0; i < fFragments.length; i++) { |
| result.add(fFragments[i].getScriptProject().getProject()); |
| } |
| return result.toArray(new IProject[result.size()]); |
| } |
| |
| @Override |
| public ResourceTraversal[] getTraversals(ResourceMappingContext context, |
| IProgressMonitor monitor) throws CoreException { |
| List<ResourceTraversal> result = new ArrayList<>(); |
| if (context instanceof RemoteResourceMappingContext) { |
| for (int i = 0; i < fFragments.length; i++) { |
| result.add(new ResourceTraversal( |
| new IResource[] { fFragments[i].getResource() }, |
| IResource.DEPTH_ONE, 0)); |
| } |
| } else { |
| for (int i = 0; i < fFragments.length; i++) { |
| result.add( |
| new LocalPackageFragementTraversal(fFragments[i])); |
| } |
| } |
| return result.toArray(new ResourceTraversal[result.size()]); |
| } |
| |
| @Override |
| public String getModelProviderId() { |
| return ScriptModelProvider.DLTK_MODEL_PROVIDER_ID; |
| } |
| } |
| |
| public static ResourceMapping create(IModelElement element) { |
| switch (element.getElementType()) { |
| case IModelElement.TYPE: |
| return create((IType) element); |
| case IModelElement.SOURCE_MODULE: |
| return create((ISourceModule) element); |
| case IModelElement.SCRIPT_FOLDER: |
| return create((IScriptFolder) element); |
| case IModelElement.PROJECT_FRAGMENT: |
| return create((IProjectFragment) element); |
| case IModelElement.SCRIPT_PROJECT: |
| return create((IScriptProject) element); |
| case IModelElement.SCRIPT_MODEL: |
| return create((IScriptModel) element); |
| default: |
| return null; |
| } |
| |
| } |
| |
| public static ResourceMapping create(final IScriptModel model) { |
| return new ScriptModelResourceMapping(model); |
| } |
| |
| public static ResourceMapping create(final IScriptProject project) { |
| return new ScriptProjectResourceMapping(project); |
| } |
| |
| public static ResourceMapping create(final IProjectFragment root) { |
| if (root.isExternal()) |
| return null; |
| return new PackageFragementRootResourceMapping(root); |
| } |
| |
| public static ResourceMapping create(final IScriptFolder pack) { |
| // test if in an archive |
| IProjectFragment root = (IProjectFragment) pack |
| .getAncestor(IModelElement.PROJECT_FRAGMENT); |
| if (!root.isArchive()) { |
| return new ScriptFolderResourceMapping(pack); |
| } |
| return null; |
| } |
| |
| public static ResourceMapping create(ISourceModule unit) { |
| if ((unit == null) || (unit.getResource() == null)) |
| return null; |
| return new SourceModuleResourceMapping(unit.getPrimary()); |
| } |
| |
| public static ResourceMapping create(IType type) { |
| // top level types behave like the CU |
| IModelElement parent = type.getParent(); |
| if (parent instanceof ISourceModule) { |
| return create((ISourceModule) parent); |
| } |
| return null; |
| } |
| |
| public static ResourceMapping create(LogicalPackage logicalPackage) { |
| IScriptFolder[] fragments = logicalPackage.getFragments(); |
| List toProcess = new ArrayList(fragments.length); |
| for (int i = 0; i < fragments.length; i++) { |
| // only add if not part of an archive |
| IProjectFragment root = (IProjectFragment) fragments[i] |
| .getAncestor(IModelElement.PROJECT_FRAGMENT); |
| if (!root.isArchive()) { |
| toProcess.add(fragments[i]); |
| } |
| } |
| if (toProcess.size() == 0) |
| return null; |
| return new LogicalPackageResourceMapping((IScriptFolder[]) toProcess |
| .toArray(new IScriptFolder[toProcess.size()])); |
| } |
| } |