/******************************************************************************* * Copyright (c) 2000, 2006 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.rubypeople.rdt.internal.corext.util; import java.util.ArrayList; import java.util.List; 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.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyModel; import org.rubypeople.rdt.core.IRubyProject; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceFolder; import org.rubypeople.rdt.core.ISourceFolderRoot; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.model.RubyModelProvider; /** * An abstract super class to describe mappings from a Ruby element to a * set of resources. The class also provides factory methods to create * resource mappings. * * @since 3.1 */ public abstract class RubyElementResourceMapping extends ResourceMapping { protected RubyElementResourceMapping() { } public IRubyElement getRubyElement() { Object o= getModelObject(); if (o instanceof IRubyElement) return (IRubyElement)o; return null; } public boolean equals(Object obj) { if (!(obj instanceof RubyElementResourceMapping)) return false; return getRubyElement().equals(((RubyElementResourceMapping)obj).getRubyElement()); } public int hashCode() { IRubyElement javaElement= getRubyElement(); if (javaElement == null) return super.hashCode(); return javaElement.hashCode(); } public String getModelProviderId() { return RubyModelProvider.RUBY_MODEL_PROVIDER_ID; } public boolean contains(ResourceMapping mapping) { if (mapping instanceof RubyElementResourceMapping) { RubyElementResourceMapping javaMapping = (RubyElementResourceMapping) mapping; IRubyElement element = getRubyElement(); IRubyElement other = javaMapping.getRubyElement(); if (other != null && element != null) return element.getPath().isPrefixOf(other.getPath()); } return false; } //---- the factory code --------------------------------------------------------------- private static final class RubyModelResourceMapping extends RubyElementResourceMapping { private final IRubyModel fRubyModel; private RubyModelResourceMapping(IRubyModel model) { Assert.isNotNull(model); fRubyModel= model; } public Object getModelObject() { return fRubyModel; } public IProject[] getProjects() { IRubyProject[] projects= null; try { projects= fRubyModel.getRubyProjects(); } catch (RubyModelException e) { RubyPlugin.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; } public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor) throws CoreException { IRubyProject[] projects= fRubyModel.getRubyProjects(); 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 RubyProjectResourceMapping extends RubyElementResourceMapping { private final IRubyProject fProject; private RubyProjectResourceMapping(IRubyProject project) { Assert.isNotNull(project); fProject= project; } public Object getModelObject() { return fProject; } public IProject[] getProjects() { return new IProject[] {fProject.getProject() }; } 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 RubyElementResourceMapping { private final ISourceFolderRoot fRoot; private PackageFragementRootResourceMapping(ISourceFolderRoot root) { Assert.isNotNull(root); fRoot= root; } public Object getModelObject() { return fRoot; } public IProject[] getProjects() { return new IProject[] {fRoot.getRubyProject().getProject() }; } 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 ISourceFolder fPack; public LocalPackageFragementTraversal(ISourceFolder pack) throws CoreException { super(new IResource[] {pack.getResource()}, IResource.DEPTH_ONE, 0); fPack= pack; } 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 SourceFolderResourceMapping extends RubyElementResourceMapping { private final ISourceFolder fPack; private SourceFolderResourceMapping(ISourceFolder pack) { Assert.isNotNull(pack); fPack= pack; } public Object getModelObject() { return fPack; } public IProject[] getProjects() { return new IProject[] { fPack.getRubyProject().getProject() }; } 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 { return new ResourceTraversal[] { new LocalPackageFragementTraversal(fPack) }; } } 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(ISourceFolder pack) throws CoreException { List 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()) && file.isDerived()) //$NON-NLS-1$ continue; result.add(member); } } } return (IFile[])result.toArray(new IFile[result.size()]); } private static final class RubyScriptResourceMapping extends RubyElementResourceMapping { private final IRubyScript fUnit; private RubyScriptResourceMapping(IRubyScript unit) { Assert.isNotNull(unit); fUnit= unit; } public Object getModelObject() { return fUnit; } public IProject[] getProjects() { return new IProject[] {fUnit.getRubyProject().getProject() }; } public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor) throws CoreException { return new ResourceTraversal[] { new ResourceTraversal(new IResource[] {fUnit.getResource()}, IResource.DEPTH_ONE, 0) }; } } public static ResourceMapping create(IRubyElement element) { switch (element.getElementType()) { case IRubyElement.TYPE: return create((IType)element); case IRubyElement.SCRIPT: return create((IRubyScript)element); case IRubyElement.SOURCE_FOLDER: return create((ISourceFolder)element); case IRubyElement.SOURCE_FOLDER_ROOT: return create((ISourceFolderRoot)element); case IRubyElement.RUBY_PROJECT: return create((IRubyProject)element); case IRubyElement.RUBY_MODEL: return create((IRubyModel)element); default: return null; } } public static ResourceMapping create(final IRubyModel model) { return new RubyModelResourceMapping(model); } public static ResourceMapping create(final IRubyProject project) { return new RubyProjectResourceMapping(project); } public static ResourceMapping create(final ISourceFolderRoot root) { if (root.isExternal()) return null; return new PackageFragementRootResourceMapping(root); } public static ResourceMapping create(final ISourceFolder pack) { // test if in an archive ISourceFolderRoot root= (ISourceFolderRoot)pack.getAncestor(IRubyElement.SOURCE_FOLDER_ROOT); if (!root.isExternal()) { return new SourceFolderResourceMapping(pack); } return null; } public static ResourceMapping create(IRubyScript unit) { if (unit == null) return null; return new RubyScriptResourceMapping(unit.getPrimary()); } public static ResourceMapping create(IType type) { // top level types behave like the CU IRubyElement parent= type.getParent(); if (parent instanceof IRubyScript) { return create((IRubyScript)parent); } return null; } }