[
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;
}
}