/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
*/
package org.biojava.bio;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.biojava.bio.program.tagvalue.ChangeTable;
import org.biojava.utils.ParserException;
/**
* AnnotationChanger
remaps the values of an
* Annotation
to new values specified by a
* ValueChanger
. This will modify the values
* associated with properties, but not the property names.
*
* For writing light-weigth adaptors to project one type of
* Annotation to another using a ChangeTable.
*
* @since 1.3
* @author Matthew Pocock
*
*/
public class AnnotationChanger extends AbstractAnnotation
{
private final Annotation wrapped;
private final ChangeTable changer;
private final Map properties;
/**
* Creates a new AnnotationChanger
using the
* specified ValueChanger
to remap its values.
*
* @param wrapped an Annotation
.
* @param changer a ValueChanger
.
*/
public AnnotationChanger(Annotation wrapped, ChangeTable changer) {
this.wrapped = wrapped;
this.changer = changer;
this.properties = new MappedHash();
}
/**
* getWrapped
returns the Annotation
* being remapped.
*
* @return an Annotation
.
*/
public Annotation getWrapped() {
return wrapped;
}
/**
* getMapper
returns the ValueChanger
being
* used to remap the Annotation
.
*
* @return a ValueChanger
.
*/
public ChangeTable getChanger() {
return changer;
}
/**
* getProperties
returns the mapped contents of the
* underlying Annotation
as a Map
.
*
* @return a Map
.
*/
public Map getProperties() {
return properties;
}
/**
* propertiesAllocated
is a convenience method to see
* if we have allocated the properties Map
.
*
* @return a boolean
true if the properties have been
* allocated, false otherwise.
*/
public boolean propertiesAllocated() {
return true;
}
private class MappedHash extends AbstractMap {
public int size() {
return wrapped.asMap().size();
}
public Set entrySet() {
return new WrappedSet(wrapped.asMap().entrySet());
}
}
private class WrappedSet extends AbstractSet {
private Set entrySet;
public WrappedSet(Set entrySet) {
this.entrySet = entrySet;
}
public int size() {
return entrySet.size();
}
public Iterator iterator() {
return new Iterator() {
Iterator i = entrySet.iterator();
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
final Map.Entry entry = (Map.Entry) i.next();
return new Map.Entry() {
public Object getKey() {
return entry.getKey();
}
public Object getValue() {
try {
return changer.change(getKey(), entry.getValue());
} catch (ParserException pe) {
throw new BioError(pe);
}
}
public Object setValue(Object value) {
return entry.setValue(value);
}
};
}
public void remove() {
i.remove();
}
};
}
}
}