/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package org.absmodels.abs.plugin.builder;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Map;
import org.absmodels.abs.plugin.util.Constants;
import org.eclipse.core.resources.*;
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.Status;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import static org.absmodels.abs.plugin.util.Constants.JAVA_SOURCE_PATH;
import static org.absmodels.abs.plugin.util.Constants.MARKER_TYPE;
import static org.absmodels.abs.plugin.util.Constants.MAUDE_PATH;
import static org.absmodels.abs.plugin.util.CoreControlUnit.notifyBuildListener;
import static org.absmodels.abs.plugin.util.UtilityFunctions.deleteRecursive;
import static org.absmodels.abs.plugin.util.UtilityFunctions.getAbsNature;
import static org.absmodels.abs.plugin.util.UtilityFunctions.isABSFile;
/**
* Builds the abs files in abs projects. Automated building has to be activated for all abs files to be parsed
* and typechecked automatically.
* @author mweber
*
*/
public class AbsBuilder extends IncrementalProjectBuilder {
static class SampleDeltaVisitor implements IResourceDeltaVisitor {
final private HashSet<String> changedFiles;
final private IProgressMonitor monitor;
public SampleDeltaVisitor(HashSet<String> changedFiles, IProgressMonitor monitor){
this.changedFiles = changedFiles;
this.monitor = monitor;
}
/**
* Visits and parses all files in the ABS project that have changed since last build
*
* @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
*/
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
AbsNature nature = getAbsNature(resource);
switch (delta.getKind()) {
case IResourceDelta.ADDED:
// handle added resource
if (nature.toIncludeInScope(resource)) {
nature.parseABSFile(resource,false,monitor);
changedFiles.add(resource.getFullPath().toString());
}
break;
case IResourceDelta.REMOVED:
// handle removed resource
break;
case IResourceDelta.CHANGED:
// handle changed resource
if (nature.toIncludeInScope(resource)) {
nature.parseABSFile(resource,false,monitor);
changedFiles.add(resource.getFullPath().toString());
}
break;
}
return true;
}
}
/**
* Works through the project and parses all abs files. gets called when a full build is needed.
*
* @author mweber
*
*/
static class SampleResourceVisitor implements IResourceVisitor {
private final HashSet<String> changedFiles;
private final IProgressMonitor monitor;
public SampleResourceVisitor(IProgressMonitor monitor, HashSet<String> changedFiles){
this.monitor = monitor;
this.changedFiles = changedFiles;
}
@Override
public boolean visit(IResource resource) throws CoreException{
AbsNature nature = getAbsNature(resource);
synchronized (nature.modelLock) {
if(isABSFile(resource) && nature.toIncludeInScope(resource)){
nature.parseABSFile(resource,false,monitor);
changedFiles.add(resource.getFullPath().toString());
}
}
return true;
}
}
/**
* gets called when a build (full or partial) is requested
*
* @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int,
* java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
@SuppressWarnings("rawtypes")
@Override
protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
throws CoreException {
final AbsNature nature = getAbsNature(getProject());
synchronized (nature.modelLock) {
nature.cleanModel();
try {
new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor) throws CoreException,
InvocationTargetException, InterruptedException {
HashSet<String> changedFiles = new HashSet<String>();
fullBuild(monitor, changedFiles);
nature.typeCheckModel(monitor);
notifyBuildListener(changedFiles);
if (monitor != null)
monitor.done();
}
}.run(monitor);
} catch (InvocationTargetException e) {
throw new CoreException(new Status(IStatus.ERROR, Constants.PLUGIN_ID, "Build", e));
} catch (InterruptedException e) {
}
return null;
}
}
/**
* cleans the project by deleting all marks generated by a previous build, cleaning the model
* by removing the current AST and deleting all generated Java and Maude files
* @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected void clean(IProgressMonitor monitor) throws CoreException {
AbsNature nature = getAbsNature(getProject());
synchronized (nature.modelLock) {
getProject().deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_INFINITE);
nature.cleanModel();
// delete all Java files and classes
String javaPathString = nature.getProjectPreferenceStore().getString(JAVA_SOURCE_PATH);
cleanGeneratedFiles(javaPathString);
// delete all Maude files and classes
String maudePathString = nature.getProjectPreferenceStore().getString(MAUDE_PATH);
cleanGeneratedFiles(maudePathString);
getProject().refreshLocal(IProject.DEPTH_INFINITE, monitor);
}
}
private void cleanGeneratedFiles(String pathstring) {
if(pathstring!=null){
IPath path = new Path(pathstring);
File dir;
if (path.isAbsolute()){
dir = new File(path.toOSString());
} else {
path=getProject().getLocation().append(path);
dir=path.toFile();
}
if(dir.exists()){
deleteRecursive(dir);
}
}
}
protected void fullBuild(final IProgressMonitor monitor, HashSet<String> changedFiles)
throws CoreException {
// the visitor does the work.
getProject().accept(new SampleResourceVisitor(monitor,changedFiles));
}
protected void incrementalBuild(IResourceDelta delta,
IProgressMonitor monitor, HashSet<String> changedFiles) throws CoreException {
// the visitor does the work.
delta.accept(new SampleDeltaVisitor(changedFiles, monitor));
}
}