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 023/** 024 * This is a ChangeListener that is designed to adapt events of one type from 025 * one source to events of another type emitted by another source. For example, 026 * you could adapt events made by edits in a database to being events fired by 027 * a sequence implementation. 028 * 029 * @author Matthew Pocock 030 * @since 1.1 031 */ 032public class ChangeForwarder implements ChangeListener { 033 private final Object source; 034 private final transient ChangeSupport changeSupport; 035 036 /** 037 * Create a new ChangeForwarder for forwarding events. 038 * 039 * @param source the new source Object 040 * @param changeSupport the ChangeSupport managing the listeners 041 */ 042 public ChangeForwarder(Object source, ChangeSupport changeSupport) { 043 this.source = source; 044 this.changeSupport = changeSupport; 045 } 046 047 /** 048 * Retrieve the 'source' object for <code>ChangeEvent</code>s fired by this forwarder. 049 * 050 * @return the source Object 051 */ 052 public Object getSource() { return source; } 053 054 /** 055 * Return the underlying <code>ChangeSupport</code> instance that can be used to 056 * fire <code>ChangeEvent</code>s and mannage listeners. 057 * 058 * @return the ChangeSupport delegate 059 */ 060 public ChangeSupport changeSupport() { return changeSupport; } 061 062 /** 063 * <p> 064 * Return the new event to represent the originating event ce. 065 * </p> 066 * 067 * <p> 068 * The returned ChangeEvent is the event that will be fired, and should be 069 * built from information in the original event. If it is null, then no event 070 * will be fired. 071 * </p> 072 * 073 * <p> 074 * The default implementation just constructs a ChangeEvent of the same type 075 * that chains back to ce. 076 * </p> 077 * 078 * @param ce the originating ChangeEvent 079 * @return a new ChangeEvent to pass on, or null if no event should be sent 080 * @throws ChangeVetoException if for any reason this event can't be handled 081 */ 082 protected ChangeEvent generateEvent(ChangeEvent ce) 083 throws ChangeVetoException { 084 return new ChangeEvent( 085 getSource(), ce.getType(), 086 null, null, 087 ce 088 ); 089 } 090 091 public void preChange(ChangeEvent ce) 092 throws ChangeVetoException { 093 ChangeEvent nce = generateEvent(ce); 094 if(nce != null) { 095 // todo: this should be coupled with the synchronization in postChange 096 synchronized(changeSupport) { 097 changeSupport.firePreChangeEvent(nce); 098 } 099 } 100 } 101 102 public void postChange(ChangeEvent ce) { 103 try { 104 ChangeEvent nce = generateEvent(ce); 105 if(nce != null) { 106 // todo: this should be coupled with the synchronization in preChange 107 synchronized(changeSupport) { 108 changeSupport.firePostChangeEvent(nce); 109 } 110 } 111 } catch (ChangeVetoException cve) { 112 throw new AssertionFailure( 113 "Assertion Failure: Change was vetoed after it had been accepted by preChange", 114 cve 115 ); 116 } 117 } 118 119 /** 120 * A ChangeForwarder that systematically uses a given type and wraps the old 121 * event. 122 * 123 * @author Matthew Pocock 124 * @since 1.4 125 */ 126 public static class Retyper 127 extends ChangeForwarder{ 128 private final ChangeType type; 129 130 /** 131 * Create a new Retyper for forwarding events. 132 * 133 * @param source the new source Object 134 * @param changeSupport the ChangeSupport managing the listeners 135 * @param type the new ChangeType 136 */ 137 public Retyper(Object source, 138 ChangeSupport changeSupport, 139 ChangeType type) 140 { 141 super(source, changeSupport); 142 143 this.type = type; 144 } 145 146 public ChangeType getType() { 147 return type; 148 } 149 150 protected ChangeEvent generateEvent(ChangeEvent ce) 151 throws ChangeVetoException { 152 return new ChangeEvent(getSource(), getType(), null, null, ce); 153 } 154 } 155}