jpayne@68: package gff; jpayne@68: jpayne@68: import java.util.ArrayList; jpayne@68: jpayne@68: import fileIO.ByteStreamWriter; jpayne@68: import shared.Tools; jpayne@68: jpayne@68: public class GbffLocus { jpayne@68: jpayne@68: public GbffLocus(ArrayList lines) { jpayne@68: while(num lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: if(Tools.startsWith(line, " ")){ jpayne@68: assert(false) : line; jpayne@68: num++; jpayne@68: }else if(Tools.startsWith(line, "LOCUS ")){ jpayne@68: parseLocus(lines); jpayne@68: }else if(Tools.startsWith(line, "DEFINITION ")){ jpayne@68: parseDefinition(lines); jpayne@68: }else if(Tools.startsWith(line, "ACCESSION ")){ jpayne@68: parseAccession(lines); jpayne@68: }else if(Tools.startsWith(line, "VERSION ")){ jpayne@68: parseVersion(lines); jpayne@68: }else if(Tools.startsWith(line, "DBLINK ")){ jpayne@68: parseDBLink(lines); jpayne@68: }else if(Tools.startsWith(line, "KEYWORDS ")){ jpayne@68: parseKeywords(lines); jpayne@68: }else if(Tools.startsWith(line, "SOURCE ")){ jpayne@68: parseSource(lines); jpayne@68: }else if(Tools.startsWith(line, "REFERENCE ")){ jpayne@68: parseReference(lines); jpayne@68: }else if(Tools.startsWith(line, "COMMENT ")){ jpayne@68: parseComment(lines); jpayne@68: }else if(Tools.startsWith(line, "FEATURES ")){ jpayne@68: parseFeatures(lines); jpayne@68: }else if(Tools.startsWith(line, "CONTIG ")){ jpayne@68: parseContig(lines); jpayne@68: }else if(Tools.startsWith(line, "ORIGIN ")){ jpayne@68: parseOrigin(lines); jpayne@68: }else if(Tools.startsWith(line, "PRIMARY ")){ jpayne@68: parsePrimary(lines); jpayne@68: }else{ jpayne@68: assert(false) : "Unhandled block type: "+new String(line); jpayne@68: } jpayne@68: return num; jpayne@68: } jpayne@68: jpayne@68: private byte[] nextLine(ArrayList lines){ jpayne@68: byte[] line=null; jpayne@68: for(final int lim=lines.size()-1; num lines){ jpayne@68: return num>=lines.size() ? null : lines.get(num); jpayne@68: } jpayne@68: jpayne@68: /** Move pointer to next block start */ jpayne@68: private int advanceBlock(ArrayList lines){ jpayne@68: for(num++; num0 && line[0]!=' '){break;} jpayne@68: } jpayne@68: return num; jpayne@68: } jpayne@68: jpayne@68: /** Move pointer to next block start */ jpayne@68: private int advanceFeature(ArrayList lines){ jpayne@68: for(num++; num0 && (line[0]!=' ' || line[5]!=' ')){break;} jpayne@68: } jpayne@68: return num; jpayne@68: } jpayne@68: jpayne@68: private String trimBlockName(byte[] line){ jpayne@68: assert(line.length>=12 && line[11]==' ') : new String(line); jpayne@68: return new String(line, 12, line.length-12); jpayne@68: } jpayne@68: jpayne@68: private String toFeatureType(byte[] line){ jpayne@68: assert(line[4]==' '); jpayne@68: assert(line[5]!=' '); jpayne@68: assert(line[20]==' '); jpayne@68: int start=5, stop=6; jpayne@68: for(; stop<21 && line[stop]!=' '; stop++){} jpayne@68: return new String(line, start, stop-start); jpayne@68: } jpayne@68: jpayne@68: private int parseLocus(ArrayList lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: // assert(Tools.startsWith(line, "LOCUS")) : new String(line); jpayne@68: if(accession==null){ jpayne@68: String s=trimBlockName(line); jpayne@68: String[] split=Tools.whitespacePlus.split(s); jpayne@68: accession=split.length>0 ? split[0] : null; jpayne@68: } jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseDefinition(ArrayList lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: if(organism==null){ jpayne@68: String s=trimBlockName(line); jpayne@68: String[] split=Tools.commaPattern.split(s); jpayne@68: organism=split.length>0 ? split[0] : null; jpayne@68: } jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseAccession(ArrayList lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: if(accession==null){ jpayne@68: String s=trimBlockName(line); jpayne@68: String[] split=Tools.whitespacePlus.split(s); jpayne@68: accession=split.length>0 ? split[0] : null; jpayne@68: } jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseVersion(ArrayList lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: String s=trimBlockName(line); jpayne@68: String[] split=Tools.whitespacePlus.split(s); jpayne@68: s=split.length>0 ? split[0] : null; jpayne@68: if(accession==null || (s!=null && s.length()>1)){ jpayne@68: accession=s; jpayne@68: } jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseDBLink(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseKeywords(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseSource(ArrayList lines){ jpayne@68: byte[] line=lines.get(num); jpayne@68: if(species==null){ jpayne@68: species=trimBlockName(line); jpayne@68: } jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseReference(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseComment(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseFeatures(ArrayList lines){ jpayne@68: for(byte[] line=nextLine(lines); line!=null && line[0]==' '; line=getLine(lines)){ jpayne@68: // System.err.println(num+": "+new String(line)); jpayne@68: String type=toFeatureType(line); jpayne@68: int idx=Tools.find(type, featureTypes); jpayne@68: // System.err.println("idx="+idx+" for '"+type+"'"); jpayne@68: if(idx>=0){ jpayne@68: // System.err.println("parseFeature"); jpayne@68: parseFeature(lines, type); jpayne@68: // System.err.println(features.get(features.size()-1)); jpayne@68: }else{ jpayne@68: // System.err.println("advanceFeature"); jpayne@68: advanceFeature(lines); jpayne@68: } jpayne@68: } jpayne@68: return num; jpayne@68: } jpayne@68: jpayne@68: /** Move pointer to next block start */ jpayne@68: private int parseFeature(ArrayList lines, String type){ jpayne@68: ArrayList flist=new ArrayList(); jpayne@68: flist.add(lines.get(num)); jpayne@68: for(num++; num0 && (line[0]!=' ' || line[5]!=' ')){ jpayne@68: // assert(false) : Character.toString(line[0])+", "+Character.toString(line[5])+", "+Character.toString(line[6])+"\n"+new String(line); jpayne@68: break; jpayne@68: } jpayne@68: flist.add(line); jpayne@68: } jpayne@68: GbffFeature f=new GbffFeature(flist, type, accession); jpayne@68: if(!f.error){ jpayne@68: features.add(f); jpayne@68: }else{ jpayne@68: // System.err.println("Failed to parse feature "+f); jpayne@68: } jpayne@68: return num; jpayne@68: } jpayne@68: jpayne@68: private int parseContig(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parseOrigin(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: private int parsePrimary(ArrayList lines){ jpayne@68: return advanceBlock(lines); jpayne@68: } jpayne@68: jpayne@68: public void toGff(ByteStreamWriter bsw) { jpayne@68: final byte[] accessionB=accession.getBytes(); jpayne@68: bsw.print(seqRegB); jpayne@68: bsw.print(accessionB); jpayne@68: if(start>0 && stop>0){ jpayne@68: bsw.print(' ').print(start).print(' ').print(stop); jpayne@68: } jpayne@68: bsw.println(); jpayne@68: for(GbffFeature f : features){ jpayne@68: if(f.type==GbffFeature.CDS || f.type==GbffFeature.tRNA || f.type==GbffFeature.rRNA){ jpayne@68: if(!f.pseudo && !f.error){ jpayne@68: f.toGff(bsw); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** Line number */ jpayne@68: int num=0; jpayne@68: jpayne@68: boolean printGene=false; jpayne@68: boolean printRepeat=false; jpayne@68: jpayne@68: public static String[] featureTypes=GbffFeature.typeStrings; jpayne@68: private static final byte[] seqRegB="##sequence-region ".getBytes(); jpayne@68: jpayne@68: String accession; jpayne@68: String organism; jpayne@68: String species; jpayne@68: int start; jpayne@68: int stop; jpayne@68: ArrayList features=new ArrayList(); jpayne@68: }