blob: ecb544a84b8ab17dd7698c7c00bdc046fb30ac6c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
*
*******************************************************************************/
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()]));
}
}