/*******************************************************************************
* Copyright (c) 2010-2012, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
* 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:
* Zoltan Ujhelyi - initial API and implementation
*******************************************************************************/
package org.eclipse.incquery.tooling.ui.builder;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.incquery.tooling.core.generator.genmodel.IEiqGenmodelProvider;
import org.eclipse.incquery.tooling.core.project.IncQueryNature;
import org.eclipse.xtext.builder.IXtextBuilderParticipant;
import org.eclipse.xtext.builder.IXtextBuilderParticipant.BuildType;
import org.eclipse.xtext.builder.builderState.IBuilderState;
import org.eclipse.xtext.builder.impl.BuildContext;
import org.eclipse.xtext.builder.impl.BuildData;
import org.eclipse.xtext.builder.impl.QueuedBuildData;
import org.eclipse.xtext.builder.impl.ToBeBuilt;
import org.eclipse.xtext.builder.impl.XtextBuilder;
import org.eclipse.xtext.resource.IResourceDescription.Delta;
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
/**
* An incremental project builder for IncQuery projects. Based on the {@link XtextBuilder} class, but simplified for
* IncQuery generation.
*
* @author Zoltan Ujhelyi
*
*/
@SuppressWarnings("restriction")
public class IncQueryProjectBuilder extends XtextBuilder {
/**
* Visitor to check for specific resources (by path) in a resource delta.
*
* @author Zoltan Ujhelyi
*
*/
private static final class ChangeDetector implements IResourceDeltaVisitor {
/**
* Sets the path to look for genmodel
* @param path
*/
public ChangeDetector(IPath path) {
super();
this.path = path;
}
private final IPath path;
private boolean changeFound = false;
public boolean visit(IResourceDelta delta) throws CoreException {
if (path.equals(delta.getFullPath())) {
changeFound = true;
}
return !changeFound;
}
public boolean isChangeFound() {
return changeFound;
}
}
public static final String BUILDER_ID = IncQueryNature.BUILDER_ID;
@Inject
private IEiqGenmodelProvider genmodelProvider;
@Inject
private IXtextBuilderParticipant participant;
@Inject
private QueuedBuildData queuedBuildData;
@Inject
private IBuilderState builderState;
/**
* @param monitor
* the progress monitor to use for reporting progress to the user. It is the caller's responsibility to
* call done() on the given monitor. Accepts null, indicating that no progress should be reported and
* that the operation cannot be cancelled.
*/
@Override
protected void incrementalBuild(IResourceDelta delta, final IProgressMonitor monitor) throws CoreException {
ChangeDetector visitor = new ChangeDetector(
genmodelProvider.getGeneratorModelPath(getProject()));
delta.accept(visitor);
if (visitor.isChangeFound()) {
super.fullBuild(monitor, false);
} else {
super.incrementalBuild(delta, monitor);
}
}
/**
* Overridden to not search for @link{IXtextBuilderParticipant} but use only the IncQuery-specified one.
*/
@Override
protected void doBuild(ToBeBuilt toBeBuilt, IProgressMonitor monitor, BuildType type) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 2);
ResourceSet resourceSet = getResourceSetProvider().get(getProject());
resourceSet.getLoadOptions().put(ResourceDescriptionsProvider.NAMED_BUILDER_SCOPE, Boolean.TRUE);
if (resourceSet instanceof ResourceSetImpl) {
((ResourceSetImpl) resourceSet).setURIResourceMap(Maps.<URI, Resource> newHashMap());
}
BuildData buildData = new BuildData(getProject().getName(), resourceSet, toBeBuilt, queuedBuildData);
if (!buildData.isEmpty()) {
ImmutableList<Delta> deltas = builderState.update(buildData, progress.newChild(1));
if (participant != null) {
participant.build(new BuildContext(this, resourceSet, deltas, type), progress.newChild(1));
getProject().getWorkspace().checkpoint(false);
} else {
progress.worked(1);
}
} else {
progress.worked(2);
}
resourceSet.eSetDeliver(false);
resourceSet.getResources().clear();
resourceSet.eAdapters().clear();
}
/**
* Overridden to not search for @link{IXtextBuilderParticipant} but use only the IncQuery-specified one.
*
*/
@Override
protected void doClean(ToBeBuilt toBeBuilt, IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 2);
ImmutableList<Delta> deltas = builderState.clean(toBeBuilt.getToBeDeleted(), progress.newChild(1));
if (participant != null) {
participant.build(new BuildContext(this, getResourceSetProvider().get(getProject()), deltas,
BuildType.CLEAN), progress.newChild(1));
} else {
progress.worked(1);
}
}
}