/* * 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 org.biojava.utils.ChangeEvent; import org.biojava.utils.ChangeForwarder; import org.biojava.utils.ChangeSupport; import org.biojava.utils.ChangeType; import org.biojava.utils.Changeable; /** *

Indicates that an object has an associated annotation.

* *

Many BioJava objects will have associated unstructured * data. This should be stored in an Annotation instance. However, the * BioJava object itself will probably not want to extend the * Annotation interface directly, but rather delegate off that * functionality to an Annotation property. The Annotatable interface * indicates that there is an Annotation property. When implementing * Annotatable, you should always create a protected or private field * containing an instance of ChangeForwarder, and register it as a * ChangeListener with the associated Annotation delegate * instance.

* *
 * public class Foo extends AbstractChangeable implements Annotatable {
 *   private Annotation ann; // the associated annotation delegate
 *   protected ChangeForwarder annFor; // the event forwarder
 *
 *   public Foo() {
 *     // make the ann delegate
 *     ann = new SimpleAnnotation();
 *     // construct the forwarder so that it emits Annotatable.ANNOTATION ChangeEvents
 *     // for the Annotation.PROPERTY events it will listen for
 *     annFor = new ChangeForwarder.Retyper(this, getChangesupport( Annotatable.ANNOTATION ), 
 *                                          Annotatable.ANNOTATION );
 *     // connect the forwarder so it listens for Annotation.PROPERTY events
 *     ann.addChangeListener( annFor, Annotation.PROPERTY ); 
 *   }
 *
 *   public Annotation getAnnotation() {
 *     return ann;
 *   }
 * }
 * 
* Check if BioJava classes and interfaces extend Annotatable. This * will tell you if you should look for associated annotation. * * If an object implements Annotatable, it may well propagate * ChangeEvent notifications from the associated Annotation. You may * need to track these to maintain the state of your applications. * * Be careful to hook up the appropriate event forwarders. * * The getAnnotation() method can be implemented lazily * (instantiate the Annotation instance and event forwarders when the first * request comes in). It can also be implemented by returning throw-away * immutable Annotation instances that are built from scratch each time. * @author Matthew Pocock * @author Keith James (docs). * @author Kalle N�slund (docs) * @see org.biojavax.RichAnnotatable * @since 1.0 */ public interface Annotatable extends Changeable { /** * Signals that the associated Annotation has altered in some way. The * chainedEvent property should refer back to the event fired by the * Annotation object. */ public static final ChangeType ANNOTATION = new ChangeType( "the associated annotation has changed", "org.biojava.bio.Annotatable", "ANNOTATION" ); /** * Should return the associated annotation object. * * @return an Annotation object, never null */ Annotation getAnnotation(); /** *

A helper class so that you don't have to worry about * forwarding events from the Annotation object to the Annotatable * one.

* *

Once a listener is added to your Annotatable that is * interested in ANNOTATION events, then instantiate one of these * and add it as a listener to the annotation object. It will * forward the events to your listeners and translate them * accordingly.

This will ease the pain of letting your Annotatable tell its * listeners about changes in the Annotation. * * @author Matthew Pocock * * @deprecated use * new ChangeForwarder.Retyper(source, cs, Annotation.PROPERTY) * instead */ static class AnnotationForwarder extends ChangeForwarder { /** * Create a new AnnotationForwarder that will forward events for a source * using a change support. * * @param source the Object to forward events on behalf of * @param cs the change support that manages listeners */ public AnnotationForwarder(Object source, ChangeSupport cs) { super(source, cs); } protected ChangeEvent generateEvent(ChangeEvent ce) { ChangeType ct = ce.getType(); if(ct == Annotation.PROPERTY) { return new ChangeEvent( getSource(), ANNOTATION, ct ); } return null; } } }