/*******************************************************************************
* Copyright Technophobia Ltd 2012
*
* This file is part of the Substeps Eclipse Plugin.
*
* The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify
* it under the terms of the Eclipse Public License v1.0.
*
* The Substeps Eclipse Plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Eclipse Public License for more details.
*
* You should have received a copy of the Eclipse Public License
* along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>.
******************************************************************************/
package com.technophobia.substeps.syntax;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import com.technophobia.eclipse.preference.PreferenceLookup;
import com.technophobia.eclipse.transformer.FileToIFileTransformer;
import com.technophobia.substeps.FeatureEditorPlugin;
import com.technophobia.substeps.model.exception.StepImplementationException;
import com.technophobia.substeps.model.exception.SubstepsParsingException;
import com.technophobia.substeps.preferences.SubstepsPreferences;
public class MarkerSyntaxErrorReporter implements DeferredReportingSyntaxErrorReporter {
private static final Collection<String> SUBSTEPS_FILE_EXTENSIONS = Arrays.asList("feature", "substeps");
private final IProject project;
private final Map<IResource, Set<Problem>> resourceToProblemMap;
private final PreferenceLookup preferenceLookup;
public MarkerSyntaxErrorReporter(final IProject project, final PreferenceLookup preferenceLookup) {
this.project = project;
this.preferenceLookup = preferenceLookup;
this.resourceToProblemMap = new HashMap<IResource, Set<Problem>>();
}
@Override
public void applyChanges() {
final Job job = new Job("Validating Substeps models") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
clearErrorsFor(project);
if (preferenceLookup.booleanFor(SubstepsPreferences.ENABLE_PROBLEMS.key())) {
for (final Map.Entry<IResource, Set<Problem>> entry : resourceToProblemMap.entrySet()) {
final IResource resource = entry.getKey();
final Set<Problem> problems = entry.getValue();
for (final Problem problem : problems) {
problem.mark(resource);
}
}
}
return Status.OK_STATUS;
}
};
job.setRule(ResourcesPlugin.getWorkspace().getRoot());
job.schedule();
}
@Override
public void reportFeatureError(final File file, final String line, final int lineNumber, final int offset,
final String description) throws RuntimeException {
addMarker(file, line, lineNumber, offset, description);
}
@Override
public void reportFeatureError(final File file, final String line, final int lineNumber, final int offset,
final String description, final RuntimeException ex) throws RuntimeException {
addMarker(file, line, lineNumber, offset, description);
}
@Override
public void reportSubstepsError(final SubstepsParsingException ex) throws RuntimeException {
addMarker(ex.getFile(), ex.getLine(), ex.getLineNumber(), (int) ex.getOffset(), ex.getMessage());
}
@Override
public void reportStepImplError(final StepImplementationException ex) {
// TODO: Currently don't deal with errors in step impl classes
}
private void addMarker(final File file, final String line, final int lineNumber, final int offset,
final String description) {
final IFile f = new FileToIFileTransformer(project).from(file);
if (!resourceToProblemMap.containsKey(f)) {
resourceToProblemMap.put(f, new HashSet<Problem>());
}
resourceToProblemMap.get(f).add(Problem.createError(description, line, lineNumber, offset));
}
protected void clearErrorsFor(final IResource resource) {
try {
final IMarker[] markers = resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
for (final IMarker marker : markers) {
final IResource res = marker.getResource();
if (res instanceof IFile) {
final IFile file = (IFile) res;
if (SUBSTEPS_FILE_EXTENSIONS.contains(file.getFileExtension().toLowerCase())) {
try {
marker.delete();
} catch (final Throwable ex) {
// Again, nothing to do but catch a throwable
FeatureEditorPlugin.instance().error("Could not delete marker for file " + file.getName(),
ex);
}
}
}
}
} catch (final CoreException ex) {
FeatureEditorPlugin.instance().error("Could not clear problems for resource " + resource.getFullPath(), ex);
}
}
}