/* * 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.utils; /** * This is a ChangeListener that is designed to adapt events of one type from * one source to events of another type emitted by another source. For example, * you could adapt events made by edits in a database to being events fired by * a sequence implementation. * * @author Matthew Pocock * @since 1.1 */ public class ChangeForwarder implements ChangeListener { private final Object source; private final transient ChangeSupport changeSupport; /** * Create a new ChangeForwarder for forwarding events. * * @param source the new source Object * @param changeSupport the ChangeSupport managing the listeners */ public ChangeForwarder(Object source, ChangeSupport changeSupport) { this.source = source; this.changeSupport = changeSupport; } /** * Retrieve the 'source' object for ChangeEvents fired by this forwarder. * * @return the source Object */ public Object getSource() { return source; } /** * Return the underlying ChangeSupport instance that can be used to * fire ChangeEvents and mannage listeners. * * @return the ChangeSupport delegate */ public ChangeSupport changeSupport() { return changeSupport; } /** *

* Return the new event to represent the originating event ce. *

* *

* The returned ChangeEvent is the event that will be fired, and should be * built from information in the original event. If it is null, then no event * will be fired. *

* *

* The default implementation just constructs a ChangeEvent of the same type * that chains back to ce. *

* * @param ce the originating ChangeEvent * @return a new ChangeEvent to pass on, or null if no event should be sent * @throws ChangeVetoException if for any reason this event can't be handled */ protected ChangeEvent generateEvent(ChangeEvent ce) throws ChangeVetoException { return new ChangeEvent( getSource(), ce.getType(), null, null, ce ); } public void preChange(ChangeEvent ce) throws ChangeVetoException { ChangeEvent nce = generateEvent(ce); if(nce != null) { // todo: this should be coupled with the synchronization in postChange synchronized(changeSupport) { changeSupport.firePreChangeEvent(nce); } } } public void postChange(ChangeEvent ce) { try { ChangeEvent nce = generateEvent(ce); if(nce != null) { // todo: this should be coupled with the synchronization in preChange synchronized(changeSupport) { changeSupport.firePostChangeEvent(nce); } } } catch (ChangeVetoException cve) { throw new AssertionFailure( "Assertion Failure: Change was vetoed after it had been accepted by preChange", cve ); } } /** * A ChangeForwarder that systematically uses a given type and wraps the old * event. * * @author Matthew Pocock * @since 1.4 */ public static class Retyper extends ChangeForwarder{ private final ChangeType type; /** * Create a new Retyper for forwarding events. * * @param source the new source Object * @param changeSupport the ChangeSupport managing the listeners * @param type the new ChangeType */ public Retyper(Object source, ChangeSupport changeSupport, ChangeType type) { super(source, changeSupport); this.type = type; } public ChangeType getType() { return type; } protected ChangeEvent generateEvent(ChangeEvent ce) throws ChangeVetoException { return new ChangeEvent(getSource(), getType(), null, null, ce); } } }