001package org.biojava.bio.program.formats;
002
003import java.util.regex.Pattern;
004
005import org.biojava.bio.AnnotationType;
006import org.biojava.bio.CardinalityConstraint;
007import org.biojava.bio.EcNumber;
008import org.biojava.bio.PropertyConstraint;
009import org.biojava.bio.program.tagvalue.BoundaryFinder;
010import org.biojava.bio.program.tagvalue.ChangeTable;
011import org.biojava.bio.program.tagvalue.LineSplitParser;
012import org.biojava.bio.program.tagvalue.MultiTagger;
013import org.biojava.bio.program.tagvalue.ParserListener;
014import org.biojava.bio.program.tagvalue.RegexSplitter;
015import org.biojava.bio.program.tagvalue.SimpleTagValueWrapper;
016import org.biojava.bio.program.tagvalue.TagDelegator;
017import org.biojava.bio.program.tagvalue.TagValueContext;
018import org.biojava.bio.program.tagvalue.TagValueListener;
019import org.biojava.bio.program.tagvalue.ValueChanger;
020import org.biojava.bio.symbol.Location;
021import org.biojava.utils.ParserException;
022import org.biojava.utils.lsid.LifeScienceIdentifier;
023
024public class Ligand {
025  private Ligand() {}
026
027  public static final class Enzyme
028  implements Format {
029    private static final AnnotationType ANNO_TYPE;
030    private static final LineSplitParser PARSER;
031    private static final LifeScienceIdentifier LSID;
032
033    static {
034      LSID = LifeScienceIdentifier.valueOf(
035        "open-bio.org", "format", "ligand/enzyme" );
036
037      Location NONE = CardinalityConstraint.NONE;
038      Location ANY = CardinalityConstraint.ANY;
039      Location ONE = CardinalityConstraint.ONE;
040
041      PropertyConstraint c_string =
042        new PropertyConstraint.ByClass(String.class);
043      PropertyConstraint c_ecNumber =
044        new PropertyConstraint.ByClass(EcNumber.class);
045
046      PARSER = new LineSplitParser(LineSplitParser.GENBANK);
047
048      ANNO_TYPE = new AnnotationType.Impl();
049      ANNO_TYPE.setDefaultConstraints(PropertyConstraint.NONE, NONE);
050      ANNO_TYPE.setConstraints("ENTRY", c_ecNumber, ONE);
051      ANNO_TYPE.setConstraints("NAME", c_string, ONE);
052      ANNO_TYPE.setConstraints("CLASS", c_string, ONE);
053      ANNO_TYPE.setConstraints("SYSNAME", c_string, ANY);
054      ANNO_TYPE.setConstraints("REACTION", c_string, ANY);
055      ANNO_TYPE.setConstraints("SUBSTRATE", c_string, ANY);
056      ANNO_TYPE.setConstraints("PRODUCT", c_string, ANY);
057      ANNO_TYPE.setConstraints("COMMENT", c_string, ANY);
058      ANNO_TYPE.setConstraints("REFERENCE", c_string, ANY);
059      ANNO_TYPE.setConstraints("PATHWAY", c_string, ANY);
060      ANNO_TYPE.setConstraints("GENES", c_string, ANY);
061      ANNO_TYPE.setConstraints("DISEASE", c_string, ANY);
062      ANNO_TYPE.setConstraints("MOTIF", c_string, ANY);
063      ANNO_TYPE.setConstraints("STRUCTURES", c_string, ANY);
064      ANNO_TYPE.setConstraints("DBLINKS", c_string, ANY);
065    }
066
067    public ParserListener getParserListener(TagValueListener listener) {
068      ChangeTable changeTable = new ChangeTable();
069
070      changeTable.setChanger("ENTRY", new ChangeTable.Changer() {
071        public Object change(Object value) {
072          String sv = (String) value;
073          sv = sv.substring("EC ".length(), sv.length());
074          int spc = sv.indexOf(" ");
075          if(spc != -1) { // remove obsolete - should publish this better
076            sv = sv.substring(0, spc);
077          }
078          return EcNumber.Impl.valueOf(sv);
079        }
080      });
081
082      ValueChanger valueChanger = new ValueChanger(listener, changeTable);
083
084      DollarStringCatter catter = new DollarStringCatter(valueChanger);
085
086      final Pattern ref_start = Pattern.compile("\\d+(\\s+\\[[^\\]]\\])?");
087
088      TagDelegator tagDelegator = new TagDelegator(valueChanger);
089      tagDelegator.setListener("NAME", catter);
090      tagDelegator.setListener("SYSNAME", catter);
091      tagDelegator.setListener("REACTION", catter);
092      tagDelegator.setListener("SUBSTRATE", catter);
093      tagDelegator.setListener("PRODUCT", catter);
094      tagDelegator.setListener("DEFINITION", catter);
095      tagDelegator.setListener("REFERENCE", new MultiTagger(valueChanger,
096        new BoundaryFinder() {
097          public boolean dropBoundaryValues() { return true; }
098          public boolean isBoundaryStart(Object value) {
099            // we should realy extract the UI entries
100            String sv = (String) value;
101            return ref_start.matcher(sv).matches();
102          }
103          public boolean isBoundaryEnd(Object value) { return false; }
104        })
105      );
106      return new ParserListener(PARSER, tagDelegator);
107    }
108
109    
110    public AnnotationType getType() {
111      return ANNO_TYPE;
112    }
113
114    public LifeScienceIdentifier getLSID() {
115      return LSID;
116    }
117  }
118
119  public static class Reaction
120  implements Format {
121    private static final AnnotationType ANNO_TYPE;
122    private static final LineSplitParser PARSER;
123    private static final LifeScienceIdentifier LSID;
124
125    static {
126      LSID = LifeScienceIdentifier.valueOf(
127              "open-bio.org", "format", "ligand/reaction" );
128
129      PARSER = new LineSplitParser(LineSplitParser.GENBANK);
130
131      Location NONE = CardinalityConstraint.NONE;
132      Location ANY = CardinalityConstraint.ANY;
133      Location ONE = CardinalityConstraint.ONE;
134      Location ONE_OR_MORE = CardinalityConstraint.ONE_OR_MORE;
135
136      PropertyConstraint c_string =
137        new PropertyConstraint.ByClass(String.class);
138      PropertyConstraint c_ecNumber =
139        new PropertyConstraint.ByClass(EcNumber.class);
140
141      ANNO_TYPE = new AnnotationType.Impl();
142      ANNO_TYPE.setDefaultConstraints(PropertyConstraint.NONE, NONE);
143      ANNO_TYPE.setConstraints("ENTRY", c_string, ONE);
144      ANNO_TYPE.setConstraints("NAME", c_string, ANY);
145      ANNO_TYPE.setConstraints("DEFINITION", c_string, ONE_OR_MORE);
146      ANNO_TYPE.setConstraints("EQUATION", c_string, ONE_OR_MORE);
147      ANNO_TYPE.setConstraints("PATHWAY", c_string, ANY);
148      ANNO_TYPE.setConstraints("ENZYME", c_ecNumber, ANY);
149    }
150
151    public ParserListener getParserListener(TagValueListener listener) {
152      ChangeTable changeTable = new ChangeTable();
153      changeTable.setChanger("ENZYME", FormatTools.EC_FROM_STRING);
154
155      ValueChanger valueChanger = new ValueChanger(listener, changeTable);
156
157      ChangeTable ct2 = new ChangeTable();
158      ct2.setSplitter("ENZYME", new RegexSplitter(Pattern.compile("\\S+"), 0));
159
160      ValueChanger vc2 = new ValueChanger(valueChanger, ct2);
161
162      return new ParserListener(PARSER, vc2);
163    }
164
165    public AnnotationType getType() {
166      return ANNO_TYPE;
167    }
168
169    public LifeScienceIdentifier getLSID() {
170      return LSID;
171    }
172  }
173
174  public static class Compound
175  implements Format {
176    private static final AnnotationType ANNO_TYPE;
177    private static final LineSplitParser PARSER;
178    private static final LifeScienceIdentifier LSID;
179
180    static {
181      LSID = LifeScienceIdentifier.valueOf(
182              "open-bio.org", "format", "ligand/compound" );
183
184      PARSER = new LineSplitParser(LineSplitParser.GENBANK);
185
186      Location NONE = CardinalityConstraint.NONE;
187      Location ANY = CardinalityConstraint.ANY;
188      Location ONE = CardinalityConstraint.ONE;
189      
190      PropertyConstraint c_string =
191        new PropertyConstraint.ByClass(String.class);
192      PropertyConstraint c_ecNumber =
193        new PropertyConstraint.ByClass(EcNumber.class);
194
195      ANNO_TYPE = new AnnotationType.Impl();
196      ANNO_TYPE.setDefaultConstraints(PropertyConstraint.NONE, NONE);
197      ANNO_TYPE.setConstraints("ENTRY", c_string, ONE);
198      ANNO_TYPE.setConstraints("NAME", c_string, ONE);
199      ANNO_TYPE.setConstraints("FORMULA", c_string, ANY);
200      ANNO_TYPE.setConstraints("PATHWAY", c_string, ANY);
201      ANNO_TYPE.setConstraints("REACTION", c_string, ANY);
202      ANNO_TYPE.setConstraints("ENZYME", c_ecNumber, ANY);
203      ANNO_TYPE.setConstraints("STRUCTURES", c_string, ANY);
204      ANNO_TYPE.setConstraints("DBLINKS", c_string, ANY);
205    }
206
207    public ParserListener getParserListener(TagValueListener listener) {
208      ChangeTable changeTable = new ChangeTable();
209      changeTable.setChanger("ENZYME", FormatTools.EC_FROM_STRING);
210
211      ValueChanger valueChanger = new ValueChanger(listener, changeTable);
212
213      ChangeTable ct2 = new ChangeTable();
214      RegexSplitter wordSplitter = new RegexSplitter(Pattern.compile("\\S+"), 0);
215      ct2.setSplitter("ENZYME", wordSplitter);
216      ct2.setSplitter("REACTION", wordSplitter);
217
218      ValueChanger vc2 = new ValueChanger(valueChanger, ct2);
219
220      return new ParserListener(PARSER, vc2);
221    }
222
223    public AnnotationType getType() {
224      return ANNO_TYPE;
225    }
226
227    public LifeScienceIdentifier getLSID() {
228      return LSID;
229    }
230  }
231  private static class DollarStringCatter
232  extends SimpleTagValueWrapper {
233    private StringBuffer sBuff;
234
235    public DollarStringCatter(TagValueListener listener) {
236      super(listener);
237      sBuff = new StringBuffer();
238    }
239
240    public void startTag(Object tag)
241    throws ParserException {
242      super.startTag(tag);
243
244      sBuff.setLength(0);
245    }
246
247    public void value(TagValueContext ctxt, java.lang.Object value)
248    throws ParserException {
249      String sv = (String) value;
250      if(sv.startsWith("$")) {
251        sBuff.append(sv.substring(1, sv.length()));
252      } else {
253        sBuff.append(' ');
254        sBuff.append(sv);
255      }
256    }
257
258    public void endTag()
259    throws ParserException {
260      super.value(null, sBuff.toString());
261      super.endTag();
262
263      sBuff.setLength(0);
264    }
265  }
266}