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.bio.program.tagvalue;
022
023import java.util.Iterator;
024import java.util.List;
025
026import org.biojava.utils.ParserException;
027
028/**
029 * <p>
030 * Intercept the values associated with some tags and change them
031 * systematically.
032 * </p>
033 *
034 * <p>
035 * The two forms of changes that can be made are:
036 * <ul>
037 * <li>replace a single value with a new single value (e.g. changing the string
038 * "1.87" into a Double object)</li>
039 * <li>split a single value into multiple values and pass each one individualy
040 * on to the delegate e.g. "a, b, c" becomes three values "a", "b", "c".</li>
041 * </ul>
042 * </p>
043 *
044 * <p>
045 * For a given tag, changers take precendence over splitters, and explicitly
046 * registered changers or splitters take precendence over the default handlers.
047 * If there is not a specific handler for a tag and there is no default set,
048 * then the value is passed on unchanged. 
049 * </p>
050 *
051 * @author Matthew Pocock
052 * @since 1.2
053 */
054public class ValueChanger
055  extends
056    SimpleTagValueWrapper
057{
058  private ChangeTable.Changer defaultC;
059  private ChangeTable.Splitter defaultS;
060  private ChangeTable changeTable;
061  
062  private ChangeTable.Changer changer;
063  private ChangeTable.Splitter splitter;
064  
065  public ValueChanger(TagValueListener delegate) {
066    super(delegate);
067  }
068
069  /** 
070   * Create a new changer that will pass the modified event stream to a
071   * delegate.
072   *
073   * @param delegate  the TagValueListener that will receive the events
074   */
075  public ValueChanger(TagValueListener delegate, ChangeTable changeTable) {
076    super(delegate);
077    this.changeTable = changeTable;
078  }
079  
080  /**
081   * The changer that will be applied to the values of tags not registered
082   * explicitly to any changer or splitter instance.
083   *
084   * @param c  the default ChangeTable.Changer
085   */
086  public void setDefaultChanger(ChangeTable.Changer c) {
087    this.defaultC = c;
088  }
089  
090  /**
091   * Get the changer that will be applied to values of tags with no specific
092   * handler registered.
093   *
094   * @return  the default ChangeTable.Changer, or null
095   */
096  public ChangeTable.Changer getDefaultChanger() {
097    return defaultC;
098  }
099  
100  /**
101   * The splitter that will be applied to the values of tags not registered
102   * explicitly to any changer or splitter instance.
103   *
104   * @param s  the default ChangeTable.Splitter
105   */
106  public void setDefaultSplitter(ChangeTable.Splitter s) {
107    this.defaultS = s;
108  }
109
110  /**
111   * Get the splitter that will be applied to values of tags with no specific
112   * handler registered.
113   *
114   * @return  the default ChangeTable.Splitter, or null
115   */
116  public ChangeTable.Splitter getDefaultSplitter() {
117    return defaultS;
118  }
119
120  public ChangeTable getChangeTable() {
121    return changeTable;
122  }
123
124  public void setChangeTable(ChangeTable changeTable) {
125    this.changeTable = changeTable;
126  }
127  
128  public void startTag(Object tag)
129  throws ParserException {
130    if(changeTable != null) {
131      this.changer = changeTable.getChanger(tag);
132      this.splitter = changeTable.getSplitter(tag);
133    } else {
134      this.changer = null;
135      this.splitter = null;
136    }
137    
138    if(this.changer == null) {
139      this.changer = defaultC;
140    }
141    
142    if(this.splitter == null) {
143      this.splitter = defaultS;
144    }
145    
146    super.startTag(tag);
147  }
148  
149  public void value(TagValueContext ctxt, Object value)
150  throws ParserException {
151    if(this.changer != null) {
152      value = changer.change(value);
153      super.value(ctxt, value);
154    } else if(this.splitter != null) {
155      List values = splitter.split(value);
156      for(Iterator i = values.iterator(); i.hasNext(); ) {
157        Object v = i.next();
158        super.value(ctxt, v);
159      }
160    } else {
161      super.value(ctxt, value);
162    }
163  }
164}
165
166