/*
This file is part of JLoom
Copyright (C) 2006 Gereon Fassbender
Homepage: jloom.sourceforge.net
JLoom is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
This program 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 GNU General Public License for more details.
You can find a copy of the GNU General Public License along with this program
in a file called COPYING. Information can also be found at www.fsf.org or
www.gnu.org or write to the Free Software Foundation, Inc., 51 Franklin Street,
Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
created: 13.11.2007 Gereon Fassbender
$Revision$
$Date$
$Log$
*/
package net.gereon.jloom.eclipse.builder;
import java.io.*;
import java.util.*;
import net.gereon.jloom.core.TranslationMapping;
import net.gereon.jloom.eclipse.core.EclipseNames;
import net.gereon.jloom.syntax.Range;
import net.gereon.jloom.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
public class MarkerTransferor implements IResourceChangeListener
{
private final static String markerId = EclipseNames.get().getGenMarkerId();
private void transferGeneratorMarkers(IFile generator, IFile template, TranslationMapping tm) throws CoreException
{
template.deleteMarkers(markerId, false, IResource.DEPTH_ZERO);
IMarker[] markers = generator.findMarkers(null, true, IResource.DEPTH_INFINITE);
for (IMarker marker : markers) {
int start = marker.getAttribute(IMarker.CHAR_START, 0);
int end = marker.getAttribute(IMarker.CHAR_END, 1) - 1;
Log.log.finest("transfer marker: " + marker + " start=" + start + " end=" + end);
if (end < 0) { end = 0; }
assert start <= end;
int length = end - start + 1;
Range or = new Range(start, length);
Range ir = tm.getInputRange(or);
int irStart = ir.getStart();
int irEnd = ir.getEnd();
if (irEnd < irStart) {
irEnd = irStart; // at least length 1
}
IMarker m = template.createMarker(markerId);
m.setAttribute(IMarker.MESSAGE, marker.getAttribute(IMarker.MESSAGE, "[no message]"));
m.setAttribute(IMarker.SEVERITY, marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING));
m.setAttribute(IMarker.CHAR_END, irEnd + 1);
m.setAttribute(IMarker.CHAR_START, irStart);
Log.log.finest("new range: " + ir.getStart() + " - " + ir.getEnd());
}
}
private void transferGeneratorMarkers(IFile generator, IFile template)
{
Reader in = null;
try {
in = new InputStreamReader(generator.getContents());
String s = TranslationTools.getString(in);
final TranslationMapping tm = TranslationTools.readTranslationMapping(s);
if (tm != null) {
transferGeneratorMarkers(generator, template, tm);
}
else {
Log.log.warning("No translation mapping found: " + generator);
}
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
finally {
try {
in.close();
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
private void startTransfer(final IFile generator, final IFile template)
{
// WorkspaceJob instead of Job
// to avoid multiple resource-change-events
final WorkspaceJob job = new WorkspaceJob("Transfer Markers") {
public IStatus runInWorkspace(IProgressMonitor pm) {
//System.err.println(">>>>>>>>>>>>>>>>");
try {
transferGeneratorMarkers(generator, template);
}
catch (Throwable ex) {
throw new RuntimeException("Error while transferring markers: " + template.getName(), ex);
}
//System.err.println("<<<<<<<<<<<<<<<<");
return Status.OK_STATUS;
}
};
// create modify-rule instead of marker-rule
// to make sure both resources are not modified
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceRuleFactory fac = workspace.getRuleFactory();
ISchedulingRule r1 = fac.modifyRule(generator);
ISchedulingRule r2 = fac.modifyRule(template);
final ISchedulingRule r = MultiRule.combine(r1, r2);
job.setRule(r);
job.schedule();
}
private void markersChanged(IFile file)
{
Log.log.finest("file: " + file);
String name = file.getName();
if (!TranslationTools.isGeneratorFilename(name)) {
return;
}
IContainer dir = file.getParent();
String templateFilename = TranslationTools.getTemplateFilename(name);
Log.log.finer("templateFilename=" + templateFilename);
IFile template = dir.getFile(new Path(templateFilename));
assert template != null;
if (template.exists()) {
startTransfer(file, template);
//try { Thread.sleep(15000); } catch (InterruptedException ex) {}
}
else {
Log.log.fine("No template found for: " + file.getFullPath());
}
}
private Collection<IFile> collectAffectedFiles(IMarkerDelta[] deltas)
{
assert deltas != null;
Set<IFile> files = new HashSet<IFile>();
// a Set because the same file can occur several times in deltas
for (IMarkerDelta md : deltas) {
if (md.getResource() instanceof IFile) {
files.add((IFile) md.getResource());
}
}
return files;
}
public void resourceChanged(IResourceChangeEvent evt)
{
Log.log.finest("evt: " + evt);
IMarkerDelta[] deltas = evt.findMarkerDeltas(null, true);
Collection<IFile> files = collectAffectedFiles(deltas);
for (IFile file : files) {
markersChanged(file);
}
}
}