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 */
021
022
023package org.biojava.bio.dp;
024
025import java.io.Serializable;
026import java.util.Collections;
027import java.util.List;
028import java.util.Set;
029
030import org.biojava.bio.Annotatable;
031import org.biojava.bio.Annotation;
032import org.biojava.bio.dist.Distribution;
033import org.biojava.bio.symbol.Alphabet;
034import org.biojava.bio.symbol.SingletonAlphabet;
035import org.biojava.utils.AbstractChangeable;
036import org.biojava.utils.ChangeEvent;
037import org.biojava.utils.ChangeForwarder;
038import org.biojava.utils.ChangeSupport;
039import org.biojava.utils.ChangeType;
040import org.biojava.utils.ChangeVetoException;
041import org.biojava.utils.SingletonList;
042
043/**
044 * @author Matthew Pocock
045 * @author Thomas Down
046 * @author Mark Schreiber
047 */
048public class SimpleEmissionState
049  extends
050    AbstractChangeable
051  implements
052    EmissionState,
053    Serializable
054{
055  private Distribution dis;
056  private String name;
057  private Annotation ann;
058  private int [] advance;
059  private Alphabet matches;
060
061  protected transient ChangeForwarder annotationForwarder;
062  protected transient ChangeForwarder distForwarder;
063
064  public final Annotation getAnnotation() {
065    return this.ann;
066  }
067
068  public final void setAnnotation(Annotation ann)
069      throws ChangeVetoException{
070    if(!hasListeners()) {
071      this.ann = ann;
072    } else {
073      ChangeEvent ce = new ChangeEvent(
074        this, EmissionState.ANNOTATION,
075        this.ann, ann
076      );
077      ChangeSupport changeSupport = getChangeSupport(EmissionState.ANNOTATION);
078      synchronized(changeSupport) {
079        changeSupport.firePreChangeEvent(ce);
080        this.ann.removeChangeListener(annotationForwarder, Annotation.PROPERTY);
081        ann.addChangeListener(annotationForwarder, Annotation.PROPERTY);
082        this.ann = ann;
083        changeSupport.firePostChangeEvent(ce);
084      }
085    }
086  }
087
088  public final Distribution getDistribution() {
089    return this.dis;
090  }
091
092  public final void setDistribution(Distribution dis)
093  throws ChangeVetoException {
094    if(!hasListeners()) {
095      this.dis = dis;
096    } else {
097      ChangeEvent ce = new ChangeEvent(
098        this, EmissionState.DISTRIBUTION,
099        this.dis, dis
100      );
101      ChangeSupport changeSupport = getChangeSupport(EmissionState.DISTRIBUTION);
102      synchronized(changeSupport) {
103        changeSupport.firePreChangeEvent(ce);
104        if(this.dis != null) {
105          this.dis.addChangeListener(distForwarder, Distribution.WEIGHTS);
106          this.dis.addChangeListener(distForwarder, Distribution.NULL_MODEL);
107        }
108        if(dis != null) {
109          dis.addChangeListener(distForwarder, Distribution.WEIGHTS);
110          dis.addChangeListener(distForwarder, Distribution.NULL_MODEL);
111        }
112        this.dis = dis;
113        changeSupport.firePostChangeEvent(ce);
114      }
115    }
116  }
117
118  public int [] getAdvance() {
119    return advance;
120  }
121
122  public void setAdvance(int [] advance)
123  throws ChangeVetoException {
124    if(!hasListeners()) {
125      this.advance = advance;
126    } else {
127      ChangeEvent ce = new ChangeEvent(
128        this, EmissionState.ADVANCE,
129        this.advance, advance
130      );
131      ChangeSupport changeSupport = getChangeSupport(EmissionState.ADVANCE);
132      synchronized(changeSupport) {
133        changeSupport.firePreChangeEvent(ce);
134        this.advance = advance;
135        changeSupport.firePostChangeEvent(ce);
136      }
137    }
138  }
139
140  public char getToken() {
141    return this.name.charAt(0);
142  }
143
144  public final String getName() {
145    return this.name;
146  }
147
148  public final void setName(String name) {
149    this.name = name;
150  }
151
152  public Alphabet getMatches() {
153    return matches;
154  }
155
156  public Set getBases() {
157    return Collections.singleton(this);
158  }
159
160  public List getSymbols() {
161    return new SingletonList(this);
162  }
163
164  public SimpleEmissionState(
165    String name,
166    Annotation ann,
167    int [] advance,
168    Distribution dis
169  ) {
170    this.name = name;
171    this.ann = ann;
172    this.advance = advance;
173    this.dis = dis;
174    this.matches = new SingletonAlphabet(this);
175  }
176
177  public void registerWithTrainer(ModelTrainer trainer) {
178    trainer.registerDistribution(getDistribution());
179  }
180
181  protected ChangeSupport getChangeSupport(ChangeType ct){
182    ChangeSupport cs = super.getChangeSupport(ct);
183
184    if(
185            annotationForwarder == null &&
186            ct.isMatchingType(Annotatable.ANNOTATION))
187    {
188      annotationForwarder = new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY);
189      getAnnotation().addChangeListener(
190          annotationForwarder,
191          Annotatable.ANNOTATION);
192    }
193
194    if(
195            distForwarder == null &&
196            ct.isMatchingType(EmissionState.DISTRIBUTION))
197    {
198      distForwarder = new ChangeForwarder.Retyper(this, cs, EmissionState.DISTRIBUTION);
199      getDistribution().addChangeListener(
200              distForwarder,
201              Distribution.WEIGHTS);
202      getDistribution().addChangeListener(
203              distForwarder,
204              Distribution.NULL_MODEL);
205    }
206    return cs;
207  }
208}