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
022package org.biojava.bio.program.xff;
023
024import java.io.IOException;
025import java.util.Iterator;
026
027import org.biojava.bio.seq.ComponentFeature;
028import org.biojava.bio.seq.Feature;
029import org.biojava.bio.seq.FeatureHolder;
030import org.biojava.bio.seq.StrandedFeature;
031import org.biojava.bio.symbol.Location;
032import org.biojava.utils.xml.XMLWriter;
033
034/**
035 * Simple XFF writing code, ripped off from Dazzle 0.08.  It probably
036 * needs a re-write to allow custom types to be used properly, but
037 * it has enough hooks for now...
038 *
039 * @author Thomas Down
040 */
041
042public class XFFWriter {
043    private XFFHelper helper;
044
045    public XFFWriter() {
046        helper = new BasicXFFHelper();
047    }
048
049    public XFFWriter(XFFHelper h) {
050        helper = h;
051    }
052
053    private void emitFeature_xff(Feature f,
054                                 XMLWriter xw)
055        throws IOException
056    {
057        if (f instanceof ComponentFeature) {
058            ComponentFeature cf = (ComponentFeature) f;
059
060            String strand = (cf.getStrand() == StrandedFeature.POSITIVE ? "+" : "-");
061            xw.openTag("componentFeature");
062            xw.attribute("strand", strand);
063            String id = helper.getFeatureID(cf);
064            if (id != null) {
065                xw.attribute("id", id);
066            }
067            emitFeature_xff_standardBits(f, xw);
068            
069            xw.openTag("componentID");
070            xw.print(cf.getComponentSequence().getName());
071            xw.closeTag("componentID");
072            
073            xw.openTag("componentLocation");
074            emitLocation_xff(cf.getComponentLocation(), xw);
075            xw.closeTag("componentLocation");
076
077            emitDetails(xw, cf);
078
079            xw.closeTag("componentFeature");
080        } else if (f instanceof StrandedFeature && ((StrandedFeature) f).getStrand() != StrandedFeature.UNKNOWN) {
081            StrandedFeature sf = (StrandedFeature) f;
082
083            String strand = (sf.getStrand() == StrandedFeature.POSITIVE ? "+" : "-");
084            xw.openTag("strandedFeature");
085            xw.attribute("strand", strand);
086            String id = helper.getFeatureID(sf);
087            if (id != null) {
088                xw.attribute("id", id);
089            }
090            emitFeature_xff_standardBits(f, xw);
091            if (f.countFeatures() > 0)
092                emitFeature_xff_featureSet(f, xw, false);
093
094            emitDetails(xw, f);
095
096            xw.closeTag("strandedFeature");
097        } else {
098            xw.openTag("feature");
099            String id = helper.getFeatureID(f);
100            if (id != null) {
101                xw.attribute("id", id);
102            }
103            emitFeature_xff_standardBits(f, xw);
104            if (f.countFeatures() > 0)
105                emitFeature_xff_featureSet(f, xw, false);
106            
107            emitDetails(xw, f);
108
109            xw.closeTag("feature");
110        }
111    }
112
113    private void emitDetails(XMLWriter xw,
114                             Feature f)
115        throws IOException
116    {
117        xw.openTag("details");
118        helper.writeDetails(xw, f);
119        xw.closeTag("details");
120    }
121
122    private void emitFeature_xff_standardBits(Feature f,
123                                              XMLWriter xw)
124        throws IOException
125    {
126        xw.openTag("type");
127        xw.print(f.getType());
128        xw.closeTag("type");
129
130        xw.openTag("source");
131        xw.print(f.getSource());
132        xw.closeTag("source");
133
134        xw.openTag("location");
135        emitLocation_xff(f.getLocation(), xw);
136        xw.closeTag("location");
137    }
138
139    private void emitLocation_xff(Location l,
140                                  XMLWriter xw)
141        throws IOException
142    {
143        for (Iterator i = l.blockIterator(); i.hasNext(); ) {
144            Location block = (Location) i.next();
145            xw.openTag("span");
146            xw.attribute("start", "" + block.getMin());
147            xw.attribute("stop", "" + block.getMax());
148            xw.closeTag("span");
149        }
150    }
151
152    
153    private void emitFeature_xff_featureSet(FeatureHolder fh,
154                                            XMLWriter xw,
155                                            boolean explicitNamespace)
156        throws IOException
157    {
158        xw.openTag("featureSet");
159        if (explicitNamespace) {
160                xw.declareNamespace(XFFTools.XFF_NS, "");
161                xw.declareNamespace(XFFTools.XFF_BIOJAVA_NS, "biojava");
162        }
163        
164        for (Iterator fi = fh.features(); fi.hasNext(); ) {
165            Feature f = (Feature) fi.next();
166            emitFeature_xff(f, xw);
167        }
168        xw.closeTag("featureSet");
169    }
170
171    public void writeFeatureSet(FeatureHolder fh,
172                                XMLWriter xw)
173        throws IOException
174    {
175        emitFeature_xff_featureSet(fh, xw, true);
176    }
177}