package hep.aida.ref;
/**
* Implementation of IAnnotation.
*
* It keeps the exact case of added keys, but all other methods
* are not case sensitive
* @author The AIDA Team at SLAC.
*
*/
import hep.aida.IAnnotation;
import java.util.Vector;
public class Annotation implements IAnnotation, Cloneable {
protected Vector keyVector = new Vector();
protected Vector valVector = new Vector();
protected Vector stkVector = new Vector();
protected boolean fillable = true;
public static String titleKey = "Title";
public static String aidaPathKey = "AidaPath"; // Path in the local AIDA ITree
public static String fullPathKey = "FullPath"; // Path in the top-level AIDA Tree (aidaMasterTree)
/**
* Creates a new instance of Annotation.
*
*/
public Annotation() {
addItem(titleKey,"",true);
}
public Annotation(IAnnotation an) {
this();
copyAn(an);
}
public Object clone() {
try {
Annotation copy = new Annotation(this);
return copy;
} catch (Exception e) {
throw new RuntimeException("Error while cloning Annotation", e);
}
}
private void copyAn(IAnnotation an) {
int size = an.size();
for (int i=0; i<size; i++) {
String key = an.key(i);
String val = an.value(key);
boolean sticky = an.isSticky(key);
if (hasKey(key)) {
setValue(key, val);
setSticky(key, sticky);
} else {
this.addItem(key, val, sticky);
}
}
}
private String getKeyForKey(String key) {
int size = keyVector.size();
for (int i=0; i<size; i++) {
Object obj = keyVector.get(i);
if (obj instanceof String) {
String str = (String) obj;
if (str.equalsIgnoreCase(key)) return str;
}
}
return null;
}
/**
* If annotation is fillable, can modified.
* othervisw throws ReadOnlyException.
*/
public void setFillable(boolean fillable) {
this.fillable = fillable;
}
public boolean isFillable() {
return fillable;
}
/**
* Add a key/value pair with a given visibility.
*
*/
public void addItem( String key, String value ) {
if (!fillable) throw new ReadOnlyException();
addItem(key, value, false);
}
public void addItem( String key, String value, boolean sticky ) {
if (!fillable) throw new ReadOnlyException();
String localKey = getKeyForKey(key);
if ( localKey != null && keyVector.contains(localKey) ) {
setValue(localKey, value);
setSticky(localKey, sticky);
} else {
keyVector.add(key);
valVector.add(value);
stkVector.add(new Boolean(sticky));
}
}
/**
* Remove the item indicated by a given key.
*
*/
public void removeItem( String key ) {
if (!fillable) throw new ReadOnlyException();
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
int index = keyVector.indexOf(localKey);
if ( isSticky( index ) ) throw new IllegalArgumentException("Item "+key+" is sticky; it cannot be removed");
keyVector.remove(index);
valVector.remove(index);
stkVector.remove(index);
}
/**
* Retrieve the value for a given key.
* @return The value of the corresponding item.
*
*/
public String value( String key ) {
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
int index = keyVector.indexOf(localKey);
return (String)valVector.get(index);
}
/**
* Set value for a given key.
* @param key The item's key.
* @param value The new value for the correponding item.
*
*/
public void setValue( String key, String value ) {
if (!fillable) throw new ReadOnlyException();
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
int index = keyVector.indexOf(localKey);
valVector.set(index,value);
}
/**
* Get the stickyness for a given key.
* @param key The item's key.
* @return The stickyness for the corresponding item.
*
*/
public boolean isSticky(String key) {
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
int index = keyVector.indexOf(localKey);
return ((Boolean)(stkVector.get(index))).booleanValue();
}
/**
* Set stickyness for a given key.
* @param key The item's key.
* @param sticky The new stickyness for the correponding item.
*
*/
public void setSticky( String key, boolean sticky ) {
if (!fillable) throw new ReadOnlyException();
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
int index = keyVector.indexOf(localKey);
stkVector.set(index, new Boolean(sticky));
}
/**
* Get the number of items in the Annotation.
* @return The size of the Annotation.
*
*/
public int size() {
return keyVector.size();
}
/**
* Get the key corresponding to the item in a given position in the Annotation.
* @param index The item's index.
* @return The corresponding key.
*
*/
public String key(int index) {
checkIndex(index);
return (String)(keyVector.get(index));
}
/**
* Get the value corresponding to the item in a given position in the Annotation.
* @param index The item's index.
* @return The corresponding value.
*
*/
public String value(int index) {
checkIndex(index);
return (String)(valVector.get(index));
}
/**
* Get the stickyness corresponding to the item in a give position in the Annotation.
* @param index The item's index.
* @return The stickyness for the corresponding item.
*
*/
public boolean isSticky(int index) {
checkIndex(index);
return ((Boolean)(stkVector.get(index))).booleanValue();
}
/**
* Reset the contents of the Annotation.
*
*/
public void reset() {
if (!fillable) throw new ReadOnlyException();
Object[] stkVct = stkVector.toArray();
for ( int i = stkVct.length-1; i > -1; i-- ) {
if ( ! ((Boolean)stkVct[i]).booleanValue() ) {
keyVector.remove(i);
valVector.remove(i);
stkVector.remove(i);
}
}
}
/**
* Utility method to check if an index is valid for the current configuration of the Annotation.
* @param index The index to be checked.
*
*/
protected void checkIndex(int index) {
if ( index + 1 > size() ) throw new IllegalArgumentException("Index "+index+" exceeds the dimension of the Annotation: "+size());
if ( index < 0 ) throw new IllegalArgumentException("Index "+index+" cannot be negative");
}
public int findKey(String key) {
String localKey = getKeyForKey(key);
if ( localKey == null || ! keyVector.contains(localKey) ) throw new IllegalArgumentException("Item "+key+" does not exist");
return keyVector.indexOf(localKey);
}
public boolean hasKey(String key) {
String localKey = getKeyForKey(key);
return localKey != null;
}
}