Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[platform-core-dev] Code submission

Hola.

I've attached three files which demonstrate a "zero performance cost" 
implementation of the feature request described in Bug #7641 
(http://bugs.eclipse.org/bugs/show_bug.cgi?id=7641). This code was added to 
the latest code from CVS as of Friday, 1/25/02, so integrating it into the 
current code base should be trivial (if the committers decide to).

Thanks,
- Jared
Object Technology International
package org.eclipse.core.resources;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

import java.util.Map;

/**
 * A marker delta describes the change to a single marker.
 * A marker can either be added, removed or changed.
 * Marker deltas give access to the state of the marker as it
 * was (in the case of deletions and changes) before the modifying
 * operation occured.
 * <p>
 * This interface is not intended to be implemented by clients.
 * </p>
 */
public interface IMarkerDelta {
/**
 * Returns the object attribute with the given name.  The result is an instance of one
 * of the following classes: <code>String</code>, <code>Integer</code>, 
 * or <code>Boolean</code>.
 * Returns <code>null</code> if the attribute is undefined.
 * The set of valid attribute names is defined elsewhere.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 * @param attributeName the name of the attribute
 * @return the value, or <code>null</code> if the attribute is undefined.
 */
public Object getAttribute(String attributeName);
/**
 * Returns the integer-valued attribute with the given name.  
 * Returns the given default value if the attribute is undefined.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @param attributeName the name of the attribute
 * @param defaultValue the value to use if the attribute does not exist
 * @return the value or the default value if the attribute is undefined.
 */
public int getAttribute(String attributeName, int defaultValue);
/**
 * Returns the string-valued attribute with the given name.  
 * Returns the given default value if the attribute is undefined.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @param attributeName the name of the attribute
 * @param defaultValue the value to use if the attribute does not exist
 * @return the value or the default value if the attribute is undefined.
 */
public String getAttribute(String attributeName, String defaultValue);
/**
 * Returns the boolean-valued attribute with the given name.  
 * Returns the given default value if the attribute is undefined.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @param attributeName the name of the attribute
 * @param defaultValue the value to use if the attribute does not exist
 * @return the value or the default value if the attribute is undefined.
 */
public boolean getAttribute(String attributeName, boolean defaultValue);
/**
 * Returns a Map with all the attributes for the marker.  The result is a Map
 * whose keys are attributes names and whose values are attribute values.
 * Each value an instance of one of the following classes: <code>String</code>, 
 * <code>Integer</code>, or <code>Boolean</code>. If the marker has no
 * attributes then <code>null</code> is returned.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @return a map of attribute keys and values (key type : <code>String</code> 
 *		value type : <code>String</code>, <code>Integer</code>, or 
 *		<code>Boolean</code>) or <code>null</code>.
 */
public Map getAttributes();
/**
 * Returns the attributes with the given names.  The result is an array 
 * whose elements correspond to the elements of the given attribute name
 * array.  Each element is <code>null</code> or an instance of one
 * of the following classes: <code>String</code>, <code>Integer</code>, 
 * or <code>Boolean</code>.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @param attributeNames the names of the attributes
 * @return the values of the given attributes.
 */
public Object[] getAttributes(String[] attributeNames);
/**
 * Returns the names of the attributes which have been set on the marker
 * described by this change. The result is an array whose elements correspond
 * to the names of the attributes which were set on the marker when this
 * delta was created.
 * 
 * If this delta was not caused by attributes being set, this method
 * returns an empty array.
 * 
 * @return the names of the attributes which were set on the marker.
 */
public String[] getSetAttributes();
/**
 * Returns the id of the marker.  The id of a marker is unique
 * relative to the resource with which the marker is associated.
 * Marker ids are not globally unique.
 *
 * @return the id of the marker
 */
public long getId();
/**
 * Returns the kind of this marker delta: 
 * one of <code>IResourceDelta.ADDED</code>, 
 * <code>IResourceDelta.REMOVED</code>, or <code>IResourceDelta.CHANGED</code>.
 *
 * @return the kind of marker delta
 * @see IResourceDelta#ADDED
 * @see IResourceDelta#REMOVED
 * @see IResourceDelta#CHANGED
 */
public int getKind();
/**
 * Returns the marker described by this change.
 * If kind is <code>IResourceDelta.REMOVED</code>, then this is the old marker,
 * otherwise this is the new marker.  Note that if the marker was deleted,
 * the value returned cannot be used to access attributes.
 *
 * @return the marker
 */
public IMarker getMarker();
/**
 * Returns the resource with which this marker is associated. 
 *
 * @return the resource
 */
public IResource getResource();
/**
 * Returns the type of this marker.
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @return the type of this marker
 */
public String getType();
/**
 * Returns whether the type of this marker is considered to be a subtype of
 * the given marker type. 
 * <p>
 * If kind is <code>IResourceDelta.ADDED</code>, then the information is 
 * from the new marker, otherwise it is from the old marker.
 * </p>
 *
 * @return boolean <code>true</code>if the marker's type
 *		is the same as (or a subtype of) the given type.
  */
public boolean isSubtypeOf(String superType);
}
package org.eclipse.core.internal.resources;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.internal.utils.Assert;
import org.eclipse.core.internal.utils.Policy;
import java.util.Map;
/**
 * An abstract marker implementation.
 * Subclasses must implement the <code>clone</code> method, and
 * are free to declare additional field and method members.
 * <p>
 * Note: Marker objects do not store whether they are "standalone"
 * vs. "attached" to the workspace. This information is maintained
 * by the workspace.
 * </p>
 *
 * @see IMarker
 */
public class Marker extends PlatformObject implements IMarker {

	/** Marker identifier. */
	protected long id;

	/** Resource with which this marker is associated. */
	protected IResource resource;
/**
 * Constructs a new marker object. 
 */
Marker(IResource resource, long id) {
	Assert.isLegal(resource != null);
	this.resource = resource;
	this.id = id;
}
/**
 * Checks the given marker info to ensure that it is not null.
 * Throws an exception if it is.
 */
private void checkInfo(MarkerInfo info) throws CoreException {
	if (info == null) {
		String message = Policy.bind("resources.markerNotFound", Long.toString(id));
		throw new ResourceException(new ResourceStatus(IResourceStatus.MARKER_NOT_FOUND, resource.getFullPath(), message));
	}
}
/**
 * @see IMarker#delete
 */
public void delete() throws CoreException {
	try {
		getWorkspace().prepareOperation();
		getWorkspace().beginOperation(true);
		getWorkspace().getMarkerManager().removeMarker(getResource(), getId());
	} finally {
		getWorkspace().endOperation(false, null);
	}
}
/**
 * @see IMarker#equals
 */
public boolean equals(Object object) {
	if (!(object instanceof IMarker))
		return false;
	IMarker other = (IMarker) object;
	return (id == other.getId() && resource.equals(other.getResource()));
}
/**
 * @see IMarker#exists
 */
public boolean exists() {
	return getInfo() != null;
}
/**
 * @see IMarker#getAttribute
 */
public Object getAttribute(String attributeName) throws CoreException {
	Assert.isNotNull(attributeName);
	MarkerInfo info = getInfo();
	checkInfo(info);
	return info.getAttribute(attributeName);
}
/**
 * @see IMarker#getAttribute
 */
public int getAttribute(String attributeName, int defaultValue) {
	Assert.isNotNull(attributeName);
	MarkerInfo info = getInfo();
	if (info == null)
		return defaultValue;
	Object value = info.getAttribute(attributeName);
	if (value != null && value instanceof Integer)
		return ((Integer) value).intValue();
	return defaultValue;
}
/**
 * @see IMarker#getAttribute
 */
public String getAttribute(String attributeName, String defaultValue) {
	Assert.isNotNull(attributeName);
	MarkerInfo info = getInfo();
	if (info == null)
		return defaultValue;
	Object value = info.getAttribute(attributeName);
	if (value != null && value instanceof String)
		return (String) value;
	return defaultValue;
}
/**
 * @see IMarker#getAttribute
 */
public boolean getAttribute(String attributeName, boolean defaultValue) {
	Assert.isNotNull(attributeName);
	MarkerInfo info = getInfo();
	if (info == null)
		return defaultValue;
	Object value = info.getAttribute(attributeName);
	if (value != null && value instanceof Boolean)
		return ((Boolean) value).booleanValue();
	return defaultValue;
}
/**
 * @see IMarker#getAttributes()
 */
public Map getAttributes() throws CoreException {
	MarkerInfo info = getInfo();
	checkInfo(info);
	return info.getAttributes();
}
/**
 * @see IMarker#getAttributes(String[])
 */
public Object[] getAttributes(String[] attributeNames) throws CoreException {
	Assert.isNotNull(attributeNames);
	MarkerInfo info = getInfo();
	checkInfo(info);
	return info.getAttributes(attributeNames);
}
/**
 * @see IMarker#getId
 */
public long getId() {
	return id;
}
protected MarkerInfo getInfo() {
	return getWorkspace().getMarkerManager().findMarkerInfo(resource, id);
}
/**
 * @see IMarker#getResource
 */
public IResource getResource() {
	return resource;
}
/**
 * @see IMarker#getType
 */
public String getType() throws CoreException {
	MarkerInfo info = getInfo();
	checkInfo(info);
	return info.getType();
}
/**
 * Returns the workspace which manages this marker.  Returns
 * <code>null</code> if this resource does not have an associated
 * resource.
 */
private Workspace getWorkspace() {
	return resource == null ? null : (Workspace) resource.getWorkspace();
}
public int hashCode() {
	return (int) id + resource.hashCode();
}
/**
 * @see IMarker#isSubtypeOf
 */
public boolean isSubtypeOf(String type) throws CoreException {
	return getWorkspace().getMarkerManager().getCache().isSubtype(getType(), type);
}
/**
 * @see IMarker#setAttribute
 */
public void setAttribute(String attributeName, int value) throws CoreException {
	setAttribute(attributeName, new Integer(value));
}
/**
 * @see IMarker#setAttribute
 */
public void setAttribute(String attributeName, Object value) throws CoreException {
	Assert.isNotNull(attributeName);
	Workspace workspace = getWorkspace();
	MarkerManager manager = workspace.getMarkerManager();
	try {
		workspace.prepareOperation();
		workspace.beginOperation(true);
		ResourceInfo resourceInfo = ((Resource)resource).getResourceInfo(false, true);
		MarkerInfo markerInfo = (MarkerInfo)resourceInfo.getMarkers().get(id);
		checkInfo(markerInfo);
		
		//only need to generate delta info if none already
		boolean needDelta = !manager.hasDelta(resource.getFullPath(), id);
		MarkerInfo oldInfo = needDelta ? (MarkerInfo)markerInfo.clone() : null;
		markerInfo.setAttribute(attributeName, value);
		if (manager.isPersistent(markerInfo))
			resourceInfo.set(ICoreConstants.M_MARKERS_SNAP_DIRTY);
		if (needDelta) {
			MarkerDelta delta = new MarkerDelta(IResourceDelta.CHANGED, resource, oldInfo, new String[] {attributeName});
			manager.changedMarkers(resource, new MarkerDelta[] {delta});
		}
	} finally {
		workspace.endOperation(false, null);
	}
}
/**
 * @see IMarker#setAttribute
 */
public void setAttribute(String attributeName, boolean value) throws CoreException {
	setAttribute(attributeName, value ? Boolean.TRUE : Boolean.FALSE);
}
/**
 * @see IMarker#setAttributes
 */
public void setAttributes(String[] attributeNames, Object[] values) throws CoreException {
	Assert.isNotNull(attributeNames);
	Assert.isNotNull(values);
	Workspace workspace = getWorkspace();
	MarkerManager manager = workspace.getMarkerManager();
	try {
		workspace.prepareOperation();
		workspace.beginOperation(true);
		ResourceInfo resourceInfo = ((Resource)resource).getResourceInfo(false, true);
		MarkerInfo markerInfo = (MarkerInfo)resourceInfo.getMarkers().get(id);
		checkInfo(markerInfo);
		
		//only need to generate delta info if none already
		boolean needDelta = !manager.hasDelta(resource.getFullPath(), id);
		MarkerInfo oldInfo = needDelta ? (MarkerInfo)markerInfo.clone() : null;
		markerInfo.setAttributes(attributeNames, values);
		if (manager.isPersistent(markerInfo))
			resourceInfo.set(ICoreConstants.M_MARKERS_SNAP_DIRTY);
		if (needDelta) {
			MarkerDelta delta = new MarkerDelta(IResourceDelta.CHANGED, resource, oldInfo, attributeNames);
			manager.changedMarkers(resource, new MarkerDelta[] {delta});
		}
	} finally {
		workspace.endOperation(false, null);
	}
}
/**
 * @see IMarker#setAttributes
 */
public void setAttributes(Map values) throws CoreException {
	Workspace workspace = getWorkspace();
	MarkerManager manager = workspace.getMarkerManager();
	try {
		workspace.prepareOperation();
		workspace.beginOperation(true);
		ResourceInfo resourceInfo = ((Resource)resource).getResourceInfo(false, true);
		MarkerInfo markerInfo = (MarkerInfo)resourceInfo.getMarkers().get(id);
		checkInfo(markerInfo);
		
		//only need to generate delta info if none already
		boolean needDelta = !manager.hasDelta(resource.getFullPath(), id);
		MarkerInfo oldInfo = needDelta ? (MarkerInfo)markerInfo.clone() : null;
		markerInfo.setAttributes(values);
		if (manager.isPersistent(markerInfo))
			resourceInfo.set(ICoreConstants.M_MARKERS_SNAP_DIRTY);
		if (needDelta) {
			MarkerDelta delta = new MarkerDelta(IResourceDelta.CHANGED, resource, oldInfo, values);
			manager.changedMarkers(resource, new MarkerDelta[] {delta});
		}
	} finally {
		workspace.endOperation(false, null);
	}
}
void setId(int value) {
	id = value;
}
}
package org.eclipse.core.internal.resources;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

import org.eclipse.core.resources.*;
import org.eclipse.core.internal.utils.Assert;
import java.util.Map;
import java.util.Set;
/**
 * @see IMarkerDelta
 */
public class MarkerDelta implements IMarkerDelta, IMarkerSetElement {
	protected int kind;
	protected IResource resource;
	protected MarkerInfo info;
	private String[] setAttributeArray= null;
	private Map setAttributeMap= null;
	protected final static String[] noAttributes= new String[0];
/**
 * Creates a new marker delta.
 */
public MarkerDelta(int kind, IResource resource, MarkerInfo info) {
	this.kind = kind;
	this.resource = resource;
	this.info = info;
}
/**
 * Creates a new marker delta.
 */
public MarkerDelta(int kind, IResource resource, MarkerInfo info, Map setAttributes) {
	this.kind = kind;
	this.resource = resource;
	this.info = info;
	this.setAttributeMap= setAttributes;
}
/**
 * Creates a new marker delta.
 */
public MarkerDelta(int kind, IResource resource, MarkerInfo info, String[] setAttributes) {
	this.kind = kind;
	this.resource = resource;
	this.info = info;
	this.setAttributeArray= setAttributes;
}
/**
 * @see IMarkerDelta#getAttribute
 */
public Object getAttribute(String attributeName) {
	return info.getAttribute(attributeName);
}
/**
 * @see IMarkerDelta#getAttribute
 */
public int getAttribute(String attributeName, int defaultValue) {
	Object value = info.getAttribute(attributeName);
	if (value == null)
		return defaultValue;
	if (value instanceof Integer)
		return ((Integer) value).intValue();
	Assert.isTrue(false);
	// avoid compiler error
	return -1;
}
/**
 * @see IMarkerDelta#getAttribute
 */
public String getAttribute(String attributeName, String defaultValue) {
	Object value = info.getAttribute(attributeName);
	if (value == null)
		return defaultValue;
	if (value instanceof String)
		return (String) value;
	Assert.isTrue(false);
	// avoid compiler error
	return "";
}
/**
 * @see IMarkerDelta#getAttribute
 */
public boolean getAttribute(String attributeName, boolean defaultValue) {
	Object value = info.getAttribute(attributeName);
	if (value == null)
		return defaultValue;
	if (value instanceof Boolean)
		return ((Boolean) value).booleanValue();
	Assert.isTrue(false);
	// avoid compiler error
	return false;
}
/**
 * @see IMarkerDelta#getAttributes
 */
public Map getAttributes() {
	return info.getAttributes();
}
/**
 * @see IMarkerDelta#getAttributes
 */
public Object[] getAttributes(String[] attributeNames) {
	return info.getAttributes(attributeNames);
}
/**
 * @see IMarkerDelta#getSetAttributes()
 */
public String[] getSetAttributes() {
	if (setAttributeArray != null) {
		return setAttributeArray;
	} else if (setAttributeMap != null) {
		Set keys= setAttributeMap.keySet();
		String[] attributes= new String[keys.size()];
		keys.toArray(attributes);
		return attributes;
	}
	return noAttributes;
}
/**
 * @see IMarkerDelta#getId
 */
public long getId() {
	return info.getId();
}
/**
 * @see IMarkerDelta#getKind
 */
public int getKind() {
	return kind;
}
/**
 * @see IMarkerDelta#getMarker
 */
public IMarker getMarker() {
	return new Marker(resource, getId());
}
/**
 * @see IMarkerDelta#getResource
 */
public IResource getResource() {
	return resource;
}
/**
 * @see IMarkerDelta#getType
 */
public String getType() {
	return info.getType();
}
/**
 * @see IMarkerDelta#isSubtypeOf
 */
public boolean isSubtypeOf(String superType) {
	return ((Workspace) getResource().getWorkspace()).getMarkerManager().getCache().isSubtype(getType(), superType);
}

/**
 * Merge two sets of marker changes.  Both sets must be on the same resource. Use the original set
 * of changes to store the result so we don't have to build a completely different set to return.
 * 
 * add + add = N/A
 * add + remove = nothing (no delta)
 * add + change = add
 * remove + add = N/A
 * remove + remove = N/A
 * remove + change = N/A
 * change + add = N/A
 * change + change = change  (note: info held onto by the marker delta should be that of the oldest change, and not replaced when composed)
 * change + remove = remove (note: info held onto by the marker delta should be that of the oldest change, and not replaced when changed to a remove)
 */
protected static MarkerSet merge(MarkerSet oldChanges, IMarkerDelta[] newChanges) {
	if (oldChanges == null) {
		MarkerSet result = new MarkerSet(newChanges.length);
		for (int i = 0; i < newChanges.length; i++)
			result.add((MarkerDelta) newChanges[i]);
		return result;
	}
	if (newChanges == null)
		return oldChanges;

	for (int i = 0; i < newChanges.length; i++) {
		MarkerDelta newDelta = (MarkerDelta) newChanges[i];
		MarkerDelta oldDelta = (MarkerDelta) oldChanges.get(newDelta.getId());
		if (oldDelta == null) {
			oldChanges.add(newDelta);
			continue;
		}
		switch (oldDelta.getKind()) {
			case IResourceDelta.ADDED :
				switch (newDelta.getKind()) {
					case IResourceDelta.ADDED :
						// add + add = N/A
						break;
					case IResourceDelta.REMOVED :
						// add + remove = nothing
						// Remove the original ADD delta.
						oldChanges.remove(oldDelta);
						break;
					case IResourceDelta.CHANGED :
						// add + change = add
						break;
				}
				break;
			case IResourceDelta.REMOVED :
				switch (newDelta.getKind()) {
					case IResourceDelta.ADDED :
						// remove + add = N/A
						break;
					case IResourceDelta.REMOVED :
						// remove + remove = N/A
						break;
					case IResourceDelta.CHANGED :
						// remove + change = N/A
						break;
				}
				break;
			case IResourceDelta.CHANGED :
				switch (newDelta.getKind()) {
					case IResourceDelta.ADDED :
						// change + add = N/A
						break;
					case IResourceDelta.REMOVED :
						// change + remove = remove
						// Change the delta kind.
						 ((MarkerDelta) oldDelta).setKind(IResourceDelta.REMOVED);
						break;
					case IResourceDelta.CHANGED :
						// change + change = change
						break;
				}
				break;
		}
	}
	return oldChanges;
}
private void setKind(int kind) {
	this.kind = kind;
}
}

Back to the top