001package org.biojava.bio.program.tagvalue;
002
003import org.biojava.utils.ParserException;
004
005/**
006 * Joins multipel values into single values.
007 *
008 * <p>
009 * Some properties have values spread across multiple lines. For example,
010 * the properties on EMBL features can be spread across multiple lines.</p>
011 *
012 * <p>
013 * This class provides callbacks to allow event streams to be re-written
014 * so that they contain this information.
015 * </p>
016 *
017 * @since 1.4
018 * @author Matthew Pocock
019 */
020public class Aggregator extends SimpleTagValueWrapper {
021  private BoundaryFinder observer;
022  private String joiner;
023
024  // state
025  //
026  private StringBuffer value;
027  private boolean inValue;
028
029  public Aggregator(TagValueListener listener, BoundaryFinder observer, String joiner) {
030    super(listener);
031    this.observer = observer;
032    this.joiner = joiner;
033    this.value = new StringBuffer();
034  }
035
036  public BoundaryFinder getBoundaryFinder() {
037    return observer;
038  }
039  
040  public void setBoundaryFinder(BoundaryFinder finder) {
041    this.observer = finder;
042  }
043  
044  public String getJoiner() {
045    return joiner;
046  }
047  
048  public void setJoiner(String joiner) {
049    this.joiner = joiner;
050  }
051  
052  public void startTag(Object tag)
053  throws ParserException {
054    super.startTag(tag);
055    inValue = false;
056    value.setLength(0);
057  }
058  
059  public void value(TagValueContext ctxt, Object value)
060  throws ParserException {
061    boolean isStart = observer.isBoundaryStart(value);
062    boolean isEnd = observer.isBoundaryEnd(value);
063    boolean dbv = observer.dropBoundaryValues();
064    
065    if(isStart && isEnd) {
066      if(inValue) {
067        super.value(ctxt, this.value.toString());
068        this.value.setLength(0);
069        inValue = false;
070      }
071      
072      if(!dbv) {
073        super.value(ctxt, value);
074      }
075    }
076    
077    if(isStart && !isEnd) {
078      if(inValue) {
079        super.value(ctxt, this.value.toString());
080        this.value.setLength(0);
081      }
082      this.value.append(value);
083      inValue = true;
084    }
085    
086    if(!isStart && isEnd) {
087      if(!dbv) {
088        this.value.append(joiner);
089        this.value.append(value);
090      }
091      
092      super.value(ctxt, this.value.toString());
093      inValue = false;
094      this.value.setLength(0);
095    }
096    
097    if(!isStart && !isEnd) {
098      this.value.append(joiner);
099      this.value.append(value);
100      inValue = true;
101    }
102  }
103
104  public void endTag()
105  throws ParserException {
106    if(inValue) {
107      super.value(null, this.value.toString());
108      inValue = false;
109    }
110    super.endTag();
111  }
112}