/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.bio.seq.io.agave; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Iterator; import org.biojava.bio.Annotatable; import org.biojava.bio.seq.ComponentFeature; import org.biojava.bio.seq.Feature; import org.biojava.bio.seq.FeatureHolder; import org.biojava.bio.seq.Sequence; import org.biojava.bio.seq.SimpleAssembly; import org.biojava.bio.seq.StrandedFeature; import org.biojava.bio.seq.impl.SimpleSequence; /** * Writes Sequence into AGAVE XML document. The AGAVE * format is defined in agave.dtd which can be downloaded * from http://www.agavexml.org. * * @author Hanning Ni * @author Brian King */ public class AgaveWriter { /** * Implements indenting for elements. * @author Brian King */ protected class Indent { /** Base indent */ protected String mIndent = new String(INDENT); /** * Add a level of indentation */ public void indent() { mIndent += INDENT; } /** * Remove a level of indentation * */ public void unIndent() { int len = mIndent.length(); int iLen = INDENT.length(); if(len >= iLen) { mIndent = mIndent.substring(0, len - iLen); } } /** * Return the current indent * */ public String toString() { return mIndent; } } /** use a two space indent */ public static final String INDENT = " "; /** Write to XML document */ protected PrintWriter mOut; /** indent */ protected Indent mIndent; /** writes PCDATA replacing XML characters with escape entities */ protected PCDATAFilterWriter mFilter; /** * The AnnotationMap to use for getting * AGAVE XML attributes from a Sequence Annotation. */ protected AGAVEAnnotFilter mAnnotFilter; /** write DOCTYPE if true */ protected boolean mWriteDocType = true; /** * Default constructor uses generic annotation to attribute mapping. * */ public AgaveWriter() { mAnnotFilter = SimpleAnnotFilter.SIMPLE_ANNOT_FILTER_FACTORY.getInstance(); mIndent = new Indent(); } /** * Construct with data source specific annotation to attribute * mapping. * */ public AgaveWriter(AGAVEAnnotFilter filter) { mAnnotFilter = filter; mIndent = new Indent(); } /** * Set flag that determines if XML DOCTYPE is written * or not. Default is true. * */ public void setWriteDocType(boolean writeDocType) { mWriteDocType = writeDocType; } /** * Write sequence into AGAVE XML format. * @param seq maybe the or simple sequence *
     * if annotation of seq has chromosome information , generate  tag
     * if seq is SimpleAssembly, generate  tag
     * otherwise, generate  tag
     * currently  each top-level sequence is wrapped into seperated sciobj xml file
     * 
*/ public void writeSequence(Sequence seq, PrintStream os) throws IOException { mOut = new PrintWriter(os); mFilter = new PCDATAFilterWriter(mOut); mOut.println(""); if (mWriteDocType) { mOut.println(""); } writeHeader(); write(seq); writeFooter(); } /** * Write <sciobj> * */ protected void writeHeader() { mOut.println(""); } /** * Write </sciobj> */ protected void writeFooter() { mOut.println(""); mOut.flush(); } /** * * Writing Sequence. * @param seq is simple sequence or simple assembly * */ protected void write(Sequence seq) throws IOException { String chrom_num = mAnnotFilter.getChromNum( seq.getAnnotation() ); if( chrom_num != null ) { mIndent.indent(); mOut.print(mIndent); mOut.println(""); writeContig((Annotatable) seq ); mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } else { if( seq instanceof SimpleAssembly) { writeContig( (Annotatable)seq ) ; } else { writeBioSequence((Annotatable)seq); } } } /** * * */ protected void writeContig(Annotatable seq ) throws IOException { /** */ mIndent.indent(); mOut.print(mIndent); mOut.print(""); writeDbId(seq); writeNote(seq); writeAssembly(seq); writeDNA(seq) ; writeMapLocation(seq) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ protected void writeAssembly(Annotatable seq) throws IOException { /** */ mIndent.indent(); mOut.print(mIndent); mOut.println(""); if(seq instanceof SimpleSequence) write((Sequence) seq ) ; else if( seq instanceof SimpleAssembly) { for (Iterator i =((Sequence) seq).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); if( subf instanceof ComponentFeature) writeBioSequence((Annotatable) ((ComponentFeature)subf).getComponentSequence() ) ; } } mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ protected void writeBioSequence(Annotatable seq ) throws IOException { String s; mIndent.indent(); mOut.print(mIndent); mOut.print(""); // close bio_sequence tag // write content writeDbId(seq) ; writeDNA( seq ) ; writeAltIds( seq ) ; writeXrefs( seq ) ; writeSequenceMap2(seq); // THOMASD hacked this.... writeMapLocation(seq) ; writeClassification(seq); mIndent.unIndent(); mOut.print(mIndent); mOut.println(""); } /** * group sequence_map by getSource() */ protected void writeSequenceMap(Annotatable seq) throws IOException { for (Iterator i = ((FeatureHolder)seq).features(); i.hasNext();) { Feature f = (Feature) i.next(); String type = f.getSource(); if( type.equalsIgnoreCase("classification") ) continue ; // writeFeature( f ); writeSequenceMap2( f ); } } /** * * */ protected void writeClassification(Annotatable seq) throws IOException { for (Iterator i = ((FeatureHolder)seq).features(); i.hasNext();) { Feature f = (Feature) i.next(); String type = f.getSource(); if( type.equalsIgnoreCase("classification") ) { writeClassification2(f) ; } } } /** * * */ private void writeClassification2(Annotatable f) throws IOException { /** */ mOut.print(mIndent); mOut.print(""); // close map tag writeDescription( f ) ; writeIdAlias( f ) ; writeEvidence( f ) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeIdAlias(Annotatable f) throws IOException { AGAVEIdAlias[] annots = mAnnotFilter.getIdAlias(f.getAnnotation()); if( annots != null ) { mIndent.indent(); for(int i = 0 ; i < annots.length; i++) mOut.print( annots[i].toString(mIndent.toString(), INDENT )); mIndent.unIndent(); } } /** * Write SequenceMap XML * */ protected void writeSequenceMap2(Annotatable f) throws IOException { /* */ mIndent.indent(); mOut.print(mIndent); mOut.print(""); // close map tag // write content // //write note // writeNote(f) ; //ignore write computation writeAnnotations((FeatureHolder) f); mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ protected void writeAnnotations(FeatureHolder f) throws IOException // changed to FeatureHolder THOMASD { //write annotation // mIndent.indent(); mOut.print(mIndent); mOut.println(""); /* for (Iterator i = f.features(); i.hasNext(); ) { Feature feature = (Feature) i.next(); if( feature.getSource().equalsIgnoreCase("annotations") ) { f = feature ; break; } } */ for (Iterator i = f.features(); i.hasNext(); ) { Feature feature = (Feature) i.next(); String type = feature.getSource() ; if( type == null || type.equalsIgnoreCase( "seq_feature" ) ) writeSeqFeature(feature); else if( type.equalsIgnoreCase( "gene") ) writeGene( feature); else { //default mapping to comp_result // writeCompResult( feature); writeSeqFeature(feature); // THOMASD } } mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ protected void writeGene(Annotatable f) throws IOException { /** **/ mIndent.indent(); mOut.print(mIndent); mOut.print("'); // write content writeNote(f) ; writeSeqLocation( f ) ; writeXrefs( f ) ; writeEvidence(f) ; writeProperty(f, AGAVEProperty.QUALIFIER ) ; writeSubSeqFeature( f ) ; writeRelatedAnnot( f ) ; writeTranscript( f ) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ protected void writeTranscript( Annotatable f) throws IOException { /** * */ for (Iterator i = ((FeatureHolder)f).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); if( subf.getSource().equalsIgnoreCase("transcript") ) writeTranscript2(subf); } } /** * * */ private void writeTranscript2(Annotatable f) throws IOException { mIndent.indent(); mOut.print(mIndent); mOut.println(""); writeExons(f); for (Iterator i = ((FeatureHolder)f).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); String type = subf.getSource() ; if( type.equalsIgnoreCase("cds") ) writeCds(subf); else if( type.equalsIgnoreCase("mrna") ) writeMrna(subf); else if( type.equalsIgnoreCase("predicted_protein") ) writePredictedProtein(subf); } mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeExons(Annotatable f) throws IOException { String[] ids = mAnnotFilter.getExonIds(f.getAnnotation()); if( ids != null ) { mIndent.indent(); mOut.print(mIndent); mOut.println(""); for(int i = 0 ; i < ids.length; i++) { mOut.println(mIndent + INDENT + ""); } mOut.print(mIndent); mOut.println("") ; mIndent.unIndent(); } } /** * * */ private void writeCds(Annotatable f) throws IOException { mIndent.indent(); mOut.print(mIndent); mOut.println(""); writeBioSequence( f) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeMrna(Annotatable f) throws IOException { mIndent.indent(); mOut.print(mIndent); mOut.println(""); writeBioSequence( f) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writePredictedProtein(Annotatable f) throws IOException { mIndent.indent(); mOut.print(mIndent); mOut.println(""); writeBioSequence( f) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * Write SeqFeature XML */ protected void writeSeqFeature( Annotatable f) throws IOException { /* */ mIndent.indent(); mOut.print(mIndent); mOut.print("'); // write content writeNote(f) ; writeSeqLocation( f ) ; writeXrefs( f ) ; writeEvidence(f) ; writeProperty(f, AGAVEProperty.QUALIFIER ) ; writeSubSeqFeature( f ) ; writeRelatedAnnot( f ) ; mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeRelatedAnnot( Annotatable f) { AGAVERelatedAnnot[] annots = mAnnotFilter.getRelatedAnnot(f.getAnnotation()); if( annots != null ) { for(int i = 0 ; i < annots.length; i++) mOut.print( annots[i].toString(mIndent + INDENT, INDENT)); } } /** * * */ private void writeEvidence(Annotatable f) throws IOException { for (Iterator i = ((FeatureHolder)f).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); if( subf.getSource().equalsIgnoreCase("evidence") ) writeEvidence2(subf); } } /** * * */ private void writeEvidence2(Annotatable f) throws IOException { //element_ids writeElementIds( f ) ; //comp_result for (Iterator i = ((FeatureHolder)f).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); writeCompResult( subf ); } } /** * * */ private void writeElementIds(Annotatable f) throws IOException { String[] ids = mAnnotFilter.getElementIds(f.getAnnotation()); if( ids != null ) { for(int i = 0 ; i < ids.length; i++) { mOut.println(mIndent + INDENT + ""); } } } /* */ protected void writeCompResult(Annotatable f) throws IOException { mIndent.indent(); mOut.print(mIndent); mOut.print(""); writeNote( f ) ; writeMatchDesc( f ) ; writeMatchAlign( f ) ; writeQueryRegion( f ) ; writeMatchRegion( f ) ; writeProperty( f, AGAVEProperty.RESULT_PROPERTY) ; writeResultGroup( f ) ; writeRelatedAnnot(f); mOut.print(mIndent); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeResultGroup(Annotatable f) throws IOException { Iterator i = ((FeatureHolder)f).features() ; if( i == null ) //void return ; while( i.hasNext() ) { Feature subf = (Feature)i.next(); String type = subf.getSource(); if( type != null && type.equalsIgnoreCase("result_group") ) { mIndent.indent(); mOut.println( mIndent + ""); for(Iterator k = subf.features(); k.hasNext();) writeCompResult( (Feature)k.next() ) ; mOut.println(mIndent + ""); mIndent.unIndent(); } else { mIndent.indent(); mOut.println(mIndent + ""); writeCompResult( subf ) ; mOut.println(mIndent + ""); mIndent.unIndent(); } } } /** * * */ private void writeQueryRegion(Annotatable f) throws IOException { AGAVEQueryRegion s = mAnnotFilter.getQueryRegion( f.getAnnotation() ); if( s != null ) { mIndent.indent(); mOut.println( s.toString(mIndent.toString() , INDENT ) ); mIndent.unIndent(); } } /** * * */ private void writeMatchRegion(Annotatable f) throws IOException { AGAVEMatchRegion s = mAnnotFilter.getMatchRegion( f.getAnnotation() ); if( s != null ) { mIndent.indent(); mOut.println( s.toString(mIndent.toString() , INDENT ) ); mIndent.unIndent(); } } /** * * */ private void writeMatchAlign(Annotatable f) throws IOException { String s = mAnnotFilter.getMatchAlign( f.getAnnotation() ); if( s != null ) { if (s.startsWith(""); mFilter.write(s); mOut.println(""); mIndent.unIndent(); } } } /** * * */ private void writeMatchDesc(Annotatable f) throws IOException { String s = mAnnotFilter.getMatchDesc( f.getAnnotation() ); if( s != null ) { if (s.startsWith(""); mFilter.write(s); mOut.println(""); mIndent.unIndent(); } } } /** * * */ private void writeSubSeqFeature(Annotatable f ) throws IOException { for (Iterator i = ((FeatureHolder)f).features(); i.hasNext(); ) { Feature subf = (Feature)i.next(); //if the feature is not declared as //treated as seq_feature if( subf.getSource().equalsIgnoreCase("evidence") ) continue ; if( subf.getSource().equalsIgnoreCase("transcript") ) continue ; writeSeqFeature( subf); } } /** * * */ private void writeSeqLocation( Annotatable f) throws IOException { int min = ((Feature)f).getLocation().getMin(); int max = ((Feature)f).getLocation().getMax(); boolean on_complement_strand = false; if( f instanceof StrandedFeature) { int type = ((StrandedFeature)f).getStrand().getValue() ; if( type == 1 ) on_complement_strand = false ; else if( type == -1 ) on_complement_strand = true ; } mIndent.indent(); mOut.print(mIndent); mOut.print(""); mOut.print(min + ".." + max); mOut.println(""); mIndent.unIndent(); } /** * * */ private void writeDNA(Annotatable seq) throws IOException { if( seq instanceof Sequence) { int i = ((Sequence)seq).length(); if (i > 0) { mIndent.indent(); mOut.print(mIndent); mOut.print(""); int j ; for (j = 0 ; j < i / 80; j ++) { mOut.print(((Sequence)seq).subList(80 * j + 1, 80 * (j+1)).seqString() + "\n"); } mOut.print(((Sequence)seq).subList(80 * j + 1, i ).seqString()); mOut.println(""); mIndent.unIndent(); } } } /** * * */ private void writeXrefs(Annotatable f) { AGAVEXrefs[] xrefs = mAnnotFilter.getXrefs(f.getAnnotation()); if( xrefs != null ) { mIndent.indent(); for(int i = 0 ; i < xrefs.length; i++) mOut.print( xrefs[i].toString(mIndent.toString(), INDENT)); mIndent.unIndent(); } } /** * * */ private void writeAltIds(Annotatable f) throws IOException { AGAVEDbId[] db_id = mAnnotFilter.getAltIds(f.getAnnotation()); if( db_id!= null ) { mIndent.indent(); mOut.println(mIndent + ""); mIndent.indent(); for(int i = 0 ; i < db_id.length; i++) mOut.print( db_id[i].toString(mIndent.toString(), INDENT)); mIndent.unIndent(); mOut.println(mIndent + ""); mIndent.unIndent(); } } /** * * */ private void writeProperty(Annotatable f, String type) { AGAVEProperty[] aps = mAnnotFilter.getProperty( f.getAnnotation(),type) ; if( aps != null ) { mIndent.indent(); for( int index = 0 ; index < aps.length; index++) mOut.print( aps[index].toString(mIndent.toString(), INDENT)); mIndent.unIndent(); } } /** * * */ private void writeMapLocation(Annotatable f) throws IOException { AGAVEMapLocation[] mls = mAnnotFilter.getMapLocation(f.getAnnotation()); if( mls != null ) { mIndent.indent(); for(int i = 0 ; i < mls.length; i++) mOut.print( mls[i].toString(mIndent.toString(),INDENT)); mIndent.unIndent(); } } /** * * */ private void writeDbId(Annotatable f) throws IOException { AGAVEDbId db_id = (AGAVEDbId)mAnnotFilter.getDbId(f.getAnnotation()); if( db_id!= null ) { mIndent.indent(); mOut.println( db_id.toString(mIndent.toString(), INDENT) ); mIndent.unIndent(); } } /** * * */ private void writeDescription( Annotatable f) throws IOException { String s = mAnnotFilter.getDescription( f.getAnnotation() ); if( s != null ) { if (s.startsWith(""); mFilter.write(s); mOut.println(""); mIndent.unIndent(); } } } /** * * */ private void writeNote( Annotatable f) throws IOException { String note = mAnnotFilter.getNote(f.getAnnotation()); if( note!= null ) { if (note.startsWith(""); mFilter.write(note); mOut.println(""); mIndent.unIndent(); } } } }