/*******************************************************************************
* Copyright (c) 2009-2011 CWI
* 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:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Bas Basten - Bas.Basten@cwi.nl (CWI)
* * Paul Klint - Paul.Klint@cwi.nl - CWI
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
* * Davy Landman - Davy.Landman@cwi.nl
*******************************************************************************/
package org.rascalmpl.eclipse.library.util;
import java.net.URISyntaxException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.rascalmpl.eclipse.Activator;
import org.rascalmpl.interpreter.control_exceptions.Throw;
import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;
import org.rascalmpl.uri.URIUtil;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISet;
import io.usethesource.vallang.ISetWriter;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.IValueFactory;
import io.usethesource.vallang.exceptions.FactTypeUseException;
import io.usethesource.vallang.type.Type;
import io.usethesource.vallang.type.TypeFactory;
import io.usethesource.vallang.type.TypeStore;
public class Resources {
private final IValueFactory VF;
private static final TypeFactory TF = TypeFactory.getInstance();
private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace().getRoot();
private static final TypeStore store = new TypeStore();
public static final Type res = TF.abstractDataType(store, "Resource");
public static final Type root = TF.constructor(store, res, "root", TF.setType(res), "projects");
public static final Type project = TF.constructor(store, res, "project", TF.sourceLocationType(), "id", TF.setType(res), "contents");
public static final Type folder = TF.constructor(store, res, "folder", TF.sourceLocationType(), "id", TF.setType(res), "contents");
public static final Type file = TF.constructor(store, res, "file", TF.sourceLocationType(), "id");
public Resources(IValueFactory vf) {
this.VF = vf;
}
public ISet projects() {
IProject[] projects = ROOT.getProjects();
ISetWriter w = VF.setWriter();
for (IProject p : projects) {
w.insert(makeProject(p));
}
return w.done();
}
public ISet references(ISourceLocation loc) {
IProject project = getIProject(loc.getAuthority());
ISetWriter w = VF.setWriter();
try {
for (IProject r : project.getReferencedProjects()) {
w.insert(makeProject(r));
}
}
catch (CoreException e) {
// TODO what to do about this?
}
return w.done();
}
public void openProject(ISourceLocation name) {
IProject project = getIProject(name.getAuthority());
try {
project.open(new NullProgressMonitor());
} catch (CoreException e) {
throw RuntimeExceptionFactory.io(VF.string(e.getMessage()), null, null);
}
}
public void closeProject(ISourceLocation name) {
IProject project = getIProject(name.getAuthority());
try {
project.close(new NullProgressMonitor());
} catch (CoreException e) {
throw RuntimeExceptionFactory.io(VF.string(e.getMessage()), null, null);
}
}
public ISourceLocation makeProject(IProject r) {
try {
return VF.sourceLocation("project", r.getName(), "");
} catch (URISyntaxException e) {
// won't happen
throw RuntimeExceptionFactory.malformedURI("project://" + r.getName(), null, null);
}
}
public ISourceLocation location(ISourceLocation name) {
IProject project = getIProject(name.getAuthority());
String path = name.getPath();
if (path != null && path.length() != 0 && !"/".equals(path)) {
IFile file = project.getFile(path);
return VF.sourceLocation(file.getLocation().toString());
}
return VF.sourceLocation(project.getLocationURI());
}
public ISet files(ISourceLocation name) {
final String projectName = name.getAuthority();
IProject project = getIProject(projectName);
final ISetWriter w = VF.setWriter();
try {
project.accept(new IResourceVisitor() {
public boolean visit(IResource resource)
throws CoreException {
if (resource.exists() && !resource.isDerived()) {
if (resource instanceof IFile) {
w.insert(makeFile(resource));
}
}
return true;
}
});
}
catch (CoreException e) {
// TODO what to do about this?
}
return w.done();
}
public ISourceLocation makeFile(IResource resource) {
String path = resource.getProjectRelativePath().toString();
path = path.startsWith("/") ? path : "/" + path;
try {
return VF.sourceLocation(URIUtil.create("project", resource.getProject().getName(), path));
} catch (URISyntaxException e) {
throw RuntimeExceptionFactory.malformedURI("project: " + resource.getProject().getName() +" path: "+ path, null, null);
}
}
public ISourceLocation makeFile(IEditorInput activeEditorInput) {
if (activeEditorInput instanceof FileEditorInput) {
IFile actualFile = ((FileEditorInput)activeEditorInput).getFile();
return makeFile(actualFile);
}
else { // a non file editor (not part of any project, such as annotated class files
String fileName = activeEditorInput.getName();
return VF.sourceLocation(fileName);
}
}
public ISourceLocation makeFolder(IFolder folder) {
String path = folder.getProjectRelativePath().toString();
path = path.startsWith("/") ? path : "/" + path;
try {
return VF.sourceLocation(URIUtil.create("project", folder.getProject().getName(), path));
} catch (URISyntaxException e) {
throw RuntimeExceptionFactory.malformedURI("project: " + folder.getProject().getName() + " path: " + path, null, null);
}
}
public IConstructor root() {
ISetWriter projects = VF.setWriter();
for (IProject p : ROOT.getProjects()) {
if (p.exists() && p.isOpen()) {
ISet contents = getProjectContents(p);
projects.insert(VF.constructor(project, makeProject(p), contents));
}
}
return VF.constructor(root, projects.done());
}
public IConstructor getProject(ISourceLocation projectName) {
IProject p = getIProject(projectName.getAuthority());
ISet contents = getProjectContents(p);
return VF.constructor(project, projectName, contents);
}
private IProject getIProject(String projectName) {
IProject p = ROOT.getProject(projectName);
if (p != null && p.exists()) {
return p;
}
else if (!p.isOpen()) {
throw new Throw(VF.string("Project does is not open: " + projectName), (ISourceLocation) null, null);
}
else {
throw new Throw(VF.string("Project does not exist: " + projectName), (ISourceLocation) null, null);
}
}
private ISet getProjectContents(IProject project) {
final ISetWriter w = VF.setWriter();
try {
project.accept(new IResourceVisitor() {
public boolean visit(IResource resource)
throws CoreException {
if (resource instanceof IFile) {
w.insert(getFile((IFile) resource));
return false;
}
else if (resource instanceof IFolder) {
w.insert(getFolder((IFolder) resource));
return false;
}
return true;
}
}, IResource.DEPTH_ONE, false);
} catch (FactTypeUseException e) {
Activator.getInstance().logException("root", e);
} catch (CoreException e) {
Activator.getInstance().logException("root", e);
}
return w.done();
}
private IValue getFolder(IFolder resource) {
return VF.constructor(folder, makeFolder(resource), getFolderContents(resource));
}
private IValue getFile(IFile resource) {
return VF.constructor(file, makeFile(resource));
}
private ISet getFolderContents(final IFolder folder) {
final ISetWriter w = VF.setWriter();
try {
folder.accept(new IResourceVisitor() {
public boolean visit(IResource resource)
throws CoreException {
if (resource == folder) {
return true;
}
if (resource instanceof IFile) {
w.insert(getFile((IFile) resource));
return false;
}
else if (resource instanceof IFolder) {
w.insert(getFolder((IFolder) resource));
return false;
}
return true;
}
}, IResource.DEPTH_ONE, false);
} catch (FactTypeUseException e) {
// does not happen
} catch (CoreException e) {
// TODO what to do about this?
}
return w.done();
}
}