/*******************************************************************************
* Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
* 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:
* The Chisel Group, University of Victoria
*******************************************************************************/
package net.sourceforge.tagsea.resources.waypoints;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import net.sourceforge.tagsea.core.IWaypoint;
import net.sourceforge.tagsea.core.IWaypointChangeEvent;
import net.sourceforge.tagsea.core.WaypointDelta;
import net.sourceforge.tagsea.resources.IResourceWaypointAttributes;
import net.sourceforge.tagsea.resources.ResourceWaypointPlugin;
import net.sourceforge.tagsea.resources.ResourceWaypointUtils;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
/**
* Synchronizes waypoints to markers.
* @author Del Myers
*/
public class ResourceWaypointMarkerHelp {
protected static HashMap<IWaypoint, IMarker> waypointMarkerMap = new HashMap<IWaypoint, IMarker>();
protected static HashMap<IMarker, IWaypoint> markerWaypointMap = new HashMap<IMarker, IWaypoint>();
private static ResourceListener resourceListener = new ResourceListener();
private static boolean ignoreChange = false;
protected static class ResourceListener implements IResourceChangeListener {
private static class MarkerDeltaVisitor implements IResourceDeltaVisitor {
/* (non-Javadoc)
* @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
*/
//@tag tagsea.bug.171 : this visitor interferes with the class FileAccessSession when it is used inside a TagSEAOperation.
public boolean visit(IResourceDelta delta) throws CoreException {
IMarkerDelta[] mdeltas = delta.getMarkerDeltas();
for (IMarkerDelta mdelta : mdeltas) {
if (mdelta.isSubtypeOf(ResourceWaypointPlugin.MARKER_ID)) {
//check the line
IMarker marker = mdelta.getMarker();
IWaypoint waypoint = markerWaypointMap.get(marker);
if (waypoint != null)
{
int deltaLine = (Integer) mdelta.getMarker().getAttribute(IResourceWaypointAttributes.ATTR_LINE);
int waypointLine = waypoint.getIntValue(IResourceWaypointAttributes.ATTR_LINE, -1);
int deltaCharStart = (Integer) mdelta.getMarker().getAttribute(IResourceWaypointAttributes.ATTR_CHAR_START);
int deltaCharEnd = (Integer) mdelta.getMarker().getAttribute(IResourceWaypointAttributes.ATTR_CHAR_END);
int wayCharStart = waypoint.getIntValue(IResourceWaypointAttributes.ATTR_CHAR_START,-1);
int wayCharEnd = waypoint.getIntValue(IResourceWaypointAttributes.ATTR_CHAR_END,-1);
if (deltaLine != waypointLine)
{
//update the line
ignoreChange = true;
waypoint.setIntValue(IResourceWaypointAttributes.ATTR_LINE, deltaLine);
ignoreChange = false;
}
if(deltaCharStart!=wayCharStart || deltaCharEnd!=wayCharEnd)
{
//update the range
ignoreChange = true;
waypoint.setIntValue(IResourceWaypointAttributes.ATTR_CHAR_START, deltaCharStart);
waypoint.setIntValue(IResourceWaypointAttributes.ATTR_CHAR_END, deltaCharEnd);
ignoreChange = false;
}
}
}
}
return true;
}
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
public void resourceChanged(final IResourceChangeEvent event) {
//@tag tagsea.bug.171 tour.TourTest2.1194628865421.1 : temporary fix.
// TagSEAPlugin.run(new TagSEAOperation("Updating resource waypoints"){
// @Override
// public IStatus run(IProgressMonitor monitor)
// throws InvocationTargetException {
// try {
try {
event.getDelta().accept(new MarkerDeltaVisitor());
} catch (CoreException e) {
ResourceWaypointPlugin.getDefault().log(e);
}
// return Status.OK_STATUS;
// } catch (CoreException e) {
// return e.getStatus();
// }
// }}, false);
}
}
public static void listenToMarkers(boolean listen) {
if (listen) {
ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener, IResourceChangeEvent.POST_CHANGE);
} else {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceListener);
}
}
public static IMarker getMarker(IWaypoint waypoint)
{
return waypointMarkerMap.get(waypoint);
}
public static IWaypoint getWaypoint(IMarker marker) {
return markerWaypointMap.get(marker);
}
public static synchronized void synchronize(WaypointDelta delta) {
if (ignoreChange) return;
for (IWaypointChangeEvent event : delta.changes) {
try {
switch(event.getType()) {
case IWaypointChangeEvent.NEW: handleNew(event); break;
case IWaypointChangeEvent.DELETE: handleDelete(event); break;
case IWaypointChangeEvent.CHANGE:
case IWaypointChangeEvent.TAG_NAME_CHANGED:
case IWaypointChangeEvent.TAGS_CHANGED:
handleChange(event);
break;
}
} catch (CoreException e) {
}
}
}
/**
* @param event
* @throws CoreException
*/
private synchronized static void handleDelete(IWaypointChangeEvent event) throws CoreException {
IMarker marker = waypointMarkerMap.get(event.getWaypoint());
if (marker != null) {
marker.delete();
waypointMarkerMap.remove(event.getWaypoint());
markerWaypointMap.remove(marker);
}
}
/**
* @param event
* @throws CoreException
*/
private synchronized static void handleNew(IWaypointChangeEvent event) throws CoreException {
IMarker marker = waypointMarkerMap.get(event.getWaypoint());
if (marker == null) {
ResourcesPlugin.getWorkspace().
run(
getCreateRunnable(event.getWaypoint()),
getRule(event.getWaypoint()),
IWorkspace.AVOID_UPDATE,
new NullProgressMonitor()
);
}
}
/**
* @param event
* @throws CoreException
*/
private synchronized static void handleChange(IWaypointChangeEvent event) throws CoreException {
IMarker marker = waypointMarkerMap.get(event.getWaypoint());
if (marker == null) {
handleNew(event);
} else {
if (!ResourcesPlugin.getWorkspace().isTreeLocked())
ResourcesPlugin.getWorkspace().
run(
getChangeRunnable(event.getWaypoint(), marker),
getRule(event.getWaypoint()),
IWorkspace.AVOID_UPDATE,
new NullProgressMonitor()
);
}
}
/**
* @param waypoint
* @param marker
* @return
*/
private static IWorkspaceRunnable getChangeRunnable(final IWaypoint waypoint, final IMarker marker) {
IWorkspaceRunnable r= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IResource resource = ResourceWaypointUtils.getResource(waypoint);
if (resource != null) {
setMarkerAttributesToWaypoint(marker, waypoint);
}
}
};
return r;
}
private static IWorkspaceRunnable getCreateRunnable(final IWaypoint waypoint) {
IWorkspaceRunnable r= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IResource resource = ResourceWaypointUtils.getResource(waypoint);
if (resource != null) {
IMarker marker= resource.createMarker(ResourceWaypointPlugin.MARKER_ID);
setMarkerAttributesToWaypoint(marker, waypoint);
waypointMarkerMap.put(waypoint, marker);
markerWaypointMap.put(marker, waypoint);
}
}
};
return r;
}
protected static void setMarkerAttributesToWaypoint(IMarker marker, IWaypoint waypoint) throws CoreException {
String[] attrs = waypoint.getAttributes();
HashMap<String, Object> attributes = new HashMap<String, Object>();
for (String attr : attrs) {
if (IResourceWaypointAttributes.ATTR_RESOURCE.equals(attr)) continue;
Object value = waypoint.getValue(attr);
if (value != null) {
if (value instanceof Integer || value instanceof String || value instanceof Boolean) {
attributes.put(attr, value);
} else if (value instanceof Date) {
DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM);
attributes.put(attr, format.format((Date)value));
} else {
attributes.put(attr, value.toString());
}
}
}
attributes.put("waypointType", ResourceWaypointPlugin.WAYPOINT_ID);
marker.setAttributes(attributes);
waypointMarkerMap.put(waypoint, marker);
markerWaypointMap.put(marker, waypoint);
}
private static ISchedulingRule getRule(IWaypoint waypoint) {
IResource resource = ResourceWaypointUtils.getResource(waypoint);
if (resource == null) {
return ResourcesPlugin.
getWorkspace().
getRuleFactory().markerRule(
ResourcesPlugin.getWorkspace().getRoot()
);
}
return resource.getWorkspace().getRuleFactory().markerRule(resource);
}
}