001/*
002 * BioJava development code
003 * 
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 * 
009 * http://www.gnu.org/copyleft/lesser.html
010 * 
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 * 
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 * 
018 * http://www.biojava.org
019 */
020
021package org.biojava.utils;
022
023import java.io.PrintStream;
024import java.util.EventListener;
025
026/**
027 *  Interface for objects which listen to ChangeEvents. 
028 *
029 * @author     Thomas Down
030 * @author     Matthew Pocock
031 * @author     Keith James
032 * @since      1.1 
033 */
034
035public interface ChangeListener extends EventListener {
036  /**
037   * Convenience implementation which vetoes every change of which it is
038   * notified. You could add this to an object directly to stop it changing
039   * in any way, or alternatively you could add it for a specific ChangeType
040   * to stop that single item from altering.
041   */
042  final static ChangeListener ALWAYS_VETO = new AlwaysVetoListener();
043
044  /**
045   * Convenience implementation that echoes all events to out.
046   */
047  final static ChangeListener LOG_TO_OUT = new LoggingListener(System.out);
048   
049  /**
050   * <p>
051   * Called before a change takes place.
052   * </p>
053   *
054   * <p>
055   * This is your chance to stop the change by throwing a ChangeVetoException.
056   * This method does not indicate that the change will definitely take place,
057   * so it is not recomended that you take any positive action within this
058   * handler.
059   * </p>
060   *
061   * @param  cev                      
062   * An event encapsulating the change which is about 
063   * to take place.
064   * @exception  ChangeVetoException  Description of Exception 
065   * @throws                          
066   * ChangeVetoException if the receiver does not wish 
067   * this change to occur at this
068   * time.
069   */
070
071  void preChange(ChangeEvent cev) throws ChangeVetoException;
072
073
074  /**
075   * <p>
076   * Called when a change has just taken place.
077   * </p>
078   *
079   * <p>
080   * This method is the place to perform any behavior in response to the
081   * change event.
082   * </p>
083   *
084   * @param  cev  
085   * An event encapsulating the change which has 
086   * occured.
087   */
088
089  void postChange(ChangeEvent cev);
090
091  /**
092   *  An implementation that always vetoes everything. 
093   *
094   * @author     Thomas Down
095   * @author     Matthew Pocock
096   * @since      1.1 
097   */
098
099  static class AlwaysVetoListener implements ChangeListener {
100
101    /**
102     *  Private constructor.
103     */
104    protected AlwaysVetoListener() {
105    }
106
107    public void preChange(ChangeEvent cev) throws ChangeVetoException {
108      throw new ChangeVetoException(
109        cev,
110        "This object has been locked"
111      );
112    }
113
114    /**
115     * @throws AssertionFailure if this is called, as preChange should have
116     *   vetoed any change already
117     */
118    public void postChange(ChangeEvent cev) {
119      throw new AssertionFailure(
120        new ChangeVetoException(
121          cev,
122          "This object has been locked" ));
123    }
124  }
125  
126  /**
127   * A listener that remembers the ChangeEvent of the last change. Mostly for
128   * debugging.
129   * @author Mark Schreiber
130   * @since 1.5
131   */
132   
133  public class ChangeEventRecorder extends ChangeAdapter{
134      private ChangeEvent event;
135      
136      public ChangeEvent getEvent(){return this.event;}
137      
138      public void preChange(ChangeEvent cev) throws ChangeVetoException {
139          event = cev;
140      }
141  }
142  
143  /**
144   * A listener that writes information about the event stream to a PrintStream.
145   * 
146   * @author Matthew Pocock
147   * @since 1.1
148   */
149  public class LoggingListener implements ChangeListener {
150    private PrintStream out;
151    private String prefix;
152    
153    /**
154     * Create a LoggingListener that will log all events to 'out'.
155     *
156     * @param out the PrintStream to log events to
157     */
158    public LoggingListener(PrintStream out) {
159      this.out = out;
160      this.prefix = null;
161    }
162    
163    /**
164     * Create a LoggingListener that will log all events to 'out' with a prefix.
165     *
166     * @param out the PrintStream to log events to
167     * @param prefix the prefix to attach to each line of the log
168     */
169    public LoggingListener(PrintStream out, String prefix) {
170      this.out = out;
171      this.prefix = prefix;
172    }
173    
174    public void preChange(ChangeEvent cev) throws ChangeVetoException {
175      if(prefix != null) {
176        out.print(prefix);
177      }
178      out.println("preChange for event " + cev);
179    }
180    
181    public void postChange(ChangeEvent cev) {
182      if(prefix != null) {
183        out.print(prefix);
184      }
185      out.println("postChange for event " + cev);
186    }
187  }
188}
189