    public boolean readRichSequence(BufferedReader reader,
            SymbolTokenization symParser,
            RichSeqIOListener rlistener,
            Namespace ns)
            throws IllegalSymbolException, IOException, ParseException {
        tax = null;
        organism = null;
        accession = null;
        boolean hasAnotherSequence = true;
        rlistener.startSequence();
        if (ns==null) ns=RichObjectFactory.getDefaultNamespace();
        rlistener.setNamespace(ns);
        String sectionKey = null;
        int xrefCount = 0;
        do {
            List section = this.readSection(reader);
            sectionKey = ((String[])section.get(0))[0];
            if(sectionKey == null){
                String message = ParseException.newMessage(this.getClass(), accession, "No section key", "Not set", sectionToString(section));
                throw new ParseException(message);
            }
            if (sectionKey.equals(LOCUS_TAG)) {
                String loc = ((String[])section.get(0))[1];
                Matcher m = lp.matcher(loc);
                Matcher mPre87 = lpPre87.matcher(loc);
                if (m.matches()) {
                    rlistener.setName(m.group(1));
                    rlistener.setAccession(m.group(1));
                    rlistener.setVersion(Integer.parseInt(m.group(2)));
                    rlistener.setCircular(m.group(3).equals("circular"));
                    rlistener.addSequenceProperty(Terms.getMolTypeTerm(),m.group(4));
                    rlistener.addSequenceProperty(Terms.getDataClassTerm(),m.group(5));
                    rlistener.setDivision(m.group(6));
                } else if (mPre87.matches()) {
                    rlistener.setName(mPre87.group(1));
                    if (mPre87.group(3)!=null) {
                        rlistener.addSequenceProperty(Terms.getGenomicTerm(),null);
                    }
                    rlistener.addSequenceProperty(Terms.getMolTypeTerm(),mPre87.group(4));
                    rlistener.setDivision(mPre87.group(5));
                    String circular = mPre87.group(2);
                    if (circular!=null) rlistener.setCircular(true);
                } else {
                    String message = ParseException.newMessage(this.getClass(),accession,"Not Set","Bad ID line found", sectionToString(section));
                    throw new ParseException(message);
                }
            } else if (sectionKey.equals(DEFINITION_TAG)) {
                rlistener.setDescription(((String[])section.get(0))[1]);
            } else if (sectionKey.equals(SOURCE_TAG)) {
                for (int i = 1; i < section.size(); i++) {
                    sectionKey = ((String[])section.get(i))[0];
                    if (sectionKey.equals(ORGANELLE_TAG)) {
                        rlistener.addSequenceProperty(Terms.getOrganelleTerm(), ((String[])section.get(i))[1].trim());
                        break; 
                    }
                }
            } else if (sectionKey.equals(DATE_TAG)) {
                String chunk = ((String[])section.get(0))[1].trim();
                Matcher dm = dp.matcher(chunk);
                if (dm.matches()) {
                    String date = dm.group(1);
                    String rel = dm.group(3);
                    String type = dm.group(4);
                    if (type.equals("Created")) {
                        rlistener.addSequenceProperty(Terms.getDateCreatedTerm(), date);
                        rlistener.addSequenceProperty(Terms.getRelCreatedTerm(), rel);
                    } else if (type.equals("Last updated, Version ")) {
                        rlistener.addSequenceProperty(Terms.getDateUpdatedTerm(), date);
                        rlistener.addSequenceProperty(Terms.getRelUpdatedTerm(), rel);
                    } else {
                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad date type found",sectionToString(section));
                        throw new ParseException(message);
                    }
                } else {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad date line found",sectionToString(section));
                    throw new ParseException(message);
                }
            } else if (sectionKey.equals(ACCESSION_TAG)) {
                String[] accs = ((String[])section.get(0))[1].split(";");
                accession = accs[0].trim();
                rlistener.setAccession(accession);
                for (int i = 1; i < accs.length; i++) {
                    rlistener.addSequenceProperty(Terms.getAdditionalAccessionTerm(),accs[i].trim());
                }
            } else if (sectionKey.equals(VERSION_TAG)) {
                String ver = ((String[])section.get(0))[1];
                Matcher m = vp.matcher(ver);
                if (m.matches()) {
                    String verAcc = m.group(1);
                    if (!accession.equals(verAcc)) {
                        rlistener.addSequenceProperty(Terms.getAdditionalAccessionTerm(),accession);
                        accession = verAcc;
                        rlistener.setAccession(accession);
                    }
                    rlistener.setVersion(Integer.parseInt(m.group(2)));
                } else {
                    rlistener.addSequenceProperty(Terms.getVersionLineTerm(),ver);
                }
            } else if (sectionKey.equals(KEYWORDS_TAG)) {
                String val = ((String[])section.get(0))[1];
                val = val.substring(0,val.length()-1); 
                String[] kws = val.split(";");
                for (int i = 0; i < kws.length; i++) {
                    rlistener.addSequenceProperty(Terms.getKeywordTerm(), kws[i].trim());
                }
            } else if (sectionKey.equals(DATABASE_XREF_TAG)) {
                String val = ((String[])section.get(0))[1];
                val = val.substring(0,val.length()-1); 
                String[] parts = val.split(";");
                CrossRef crossRef = (CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{parts[0].trim(),parts[1].trim(), new Integer(0)});
                for (int j = 2; j < parts.length; j++) {
                    Note note = new SimpleNote(Terms.getAdditionalAccessionTerm(),parts[j].trim(),j-1);
                    try {
                        ((RichAnnotation)crossRef.getAnnotation()).addNote(note);
                    } catch (ChangeVetoException ce) {
                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "Could not annotate identifier terms",sectionToString(section));
                        ParseException pe = new ParseException(message);
                        pe.initCause(ce);
                        throw pe;
                    }
                }
                RankedCrossRef rcrossRef = new SimpleRankedCrossRef(crossRef, ++xrefCount);
                rlistener.setRankedCrossRef(rcrossRef);
            } else if (sectionKey.equals(REFERENCE_TAG) && !this.getElideReferences()) {
                String refrank = ((String[])section.get(0))[1];
                int ref_rank = Integer.parseInt(refrank.substring(1,refrank.length()-1));
                int ref_start = -999;
                int ref_end = -999;
                String consortium = null;
                String authors = null;
                String title = null;
                String locator = null;
                String pubmed = null;
                String medline = null;
                String doi = null;
                String remark = null;
                for (int i = 1; i < section.size(); i++) {
                    String key = ((String[])section.get(i))[0];
                    String val = ((String[])section.get(i))[1];
                    if (key.equals(AUTHORS_TAG)) {
                        if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                        authors = val;
                    }
                    if (key.equals(CONSORTIUM_TAG)) {
                        if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                        consortium = val;
                    }
                    if (key.equals(TITLE_TAG)) {
                        if (val.length()>1) {
                            if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                            if (val.endsWith("\"")) val = val.substring(1,val.length()-1); 
                            title = val.replace('\n',' '); 
                        } else title=null; 
                    }
                    if (key.equals(LOCATOR_TAG)) {
                        if (val.endsWith(".")) val = val.substring(0,val.length()-1); 
                        locator = val;
                    }
                    if (key.equals(REFERENCE_XREF_TAG)) {
                        String[] refs = val.split("\\.(\\s+|$)");
                        for (int j = 0 ; j < refs.length; j++) {
                            if (refs[j].trim().length()==0) continue;
                            String[] parts = refs[j].split(";");
                            String db = parts[0];
                            String ref = parts[1];
                            if (db.equalsIgnoreCase(Terms.PUBMED_KEY)) pubmed = ref;
                            else if (db.equalsIgnoreCase(Terms.MEDLINE_KEY)) medline = ref;
                            else if (db.equalsIgnoreCase(Terms.DOI_KEY)) doi = ref;
                        }
                    }
                    if (key.equals(REMARK_TAG)) remark = val.replace('\n',' '); 
                    if (key.equals(REFERENCE_POSITION_TAG)) {
                        Matcher m = rpp.matcher(val);
                        if (m.matches()) {
                            ref_start = Integer.parseInt(m.group(1));
                            if(m.group(2) != null)
                                ref_end = Integer.parseInt(m.group(3));
                        } else {
                            String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad reference line found",sectionToString(section));
                            throw new ParseException(message);
                        }
                    }
                }
                try {
                    List authSet = DocRefAuthor.Tools.parseAuthorString(authors);
                    if (consortium!=null) authSet.add(new SimpleDocRefAuthor(consortium, true, false));
                    DocRef dr = (DocRef)RichObjectFactory.getObject(SimpleDocRef.class,new Object[]{authSet,locator,title});
                    if (medline!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.MEDLINE_KEY, medline, new Integer(0)}));
                    else if (pubmed!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.PUBMED_KEY, pubmed, new Integer(0)}));
                    else if (doi!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.DOI_KEY, doi, new Integer(0)}));
                    if (!this.getElideComments()) dr.setRemark(remark);
                    RankedDocRef rdr = new SimpleRankedDocRef(dr,
                            (ref_start != -999 ? new Integer(ref_start) : null),
                            (ref_end != -999 ? new Integer(ref_end) : null),
                            ref_rank);
                    rlistener.setRankedDocRef(rdr);
                } catch (ChangeVetoException e) {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                    throw new ParseException(e, message);
                }
            } else if (sectionKey.equals(COMMENT_TAG) && !this.getElideComments()) {
                rlistener.setComment(((String[])section.get(0))[1]);
            } else if (sectionKey.equals(FEATURE_TAG) && !this.getElideFeatures()) {
                boolean seenAFeature = false;
                for (int i = 1 ; i < section.size(); i++) {
                    String key = ((String[])section.get(i))[0];
                    String val = ((String[])section.get(i))[1];
                    if (key.startsWith("/")) {
                        key = key.substring(1); 
                        val = val.replaceAll("\\s*[\\n\\r]+\\s*"," ").trim();
                        if (val.startsWith("\"")) val = val.substring(1,val.length()-1); 
                        if (key.equalsIgnoreCase("db_xref")) {
                            Matcher m = dbxp.matcher(val);
                            if (m.matches()) {
                                String dbname = m.group(1);
                                String raccession = m.group(2);
                                if (dbname.equalsIgnoreCase("taxon")) {
                                    tax = (NCBITaxon)RichObjectFactory.getObject(SimpleNCBITaxon.class, new Object[]{Integer.valueOf(raccession)});
                                    rlistener.setTaxon(tax);
                                    try {
                                        if (organism!=null) tax.addName(NCBITaxon.SCIENTIFIC,organism);
                                    } catch (ChangeVetoException e) {
                                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                        throw new ParseException(e, message);
                                    }
                                } else {
                                    try {
                                        CrossRef cr = (CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{dbname, raccession, new Integer(0)});
                                        RankedCrossRef rcr = new SimpleRankedCrossRef(cr, 0);
                                        rlistener.getCurrentFeature().addRankedCrossRef(rcr);
                                    } catch (ChangeVetoException e) {
                                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                        throw new ParseException(e, message);
                                    }
                                }
                            } else {
                                String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad dbxref found",sectionToString(section));
                                throw new ParseException(message);
                            }
                        } else if (key.equalsIgnoreCase("organism")) {
                            try {
                                organism = val;
                                if (tax!=null) tax.addName(NCBITaxon.SCIENTIFIC,organism);
                            } catch (ChangeVetoException e) {
                                String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                throw new ParseException(message);
                            }
                        } else {
                            if (key.equalsIgnoreCase("translation")) {
                                val = val.replaceAll("\\s+","");
                            }
                            rlistener.addFeatureProperty(RichObjectFactory.getDefaultOntology().getOrCreateTerm(key),val);
                        }
                    } else {
                        if (seenAFeature) rlistener.endFeature();
                        RichFeature.Template templ = new RichFeature.Template();
                        templ.annotation = new SimpleRichAnnotation();
                        templ.sourceTerm = Terms.getEMBLTerm();
                        templ.typeTerm = RichObjectFactory.getDefaultOntology().getOrCreateTerm(key);
                        templ.featureRelationshipSet = new TreeSet();
                        templ.rankedCrossRefs = new TreeSet();
                        String tidyLocStr = val.replaceAll("\\s+","");
                        templ.location = GenbankLocationParser.parseLocation(ns, accession, tidyLocStr);
                        rlistener.startFeature(templ);
                        seenAFeature = true;
                    }
                }
                if (seenAFeature) rlistener.endFeature();
            } else if (sectionKey.equals(START_SEQUENCE_TAG) && !this.getElideSymbols()) {
                StringBuffer seq = new StringBuffer();
                for (int i = 0 ; i < section.size(); i++) seq.append(((String[])section.get(i))[1]);
                try {
                    SymbolList sl = new SimpleSymbolList(symParser,
                            seq.toString().replaceAll("\\s+","").replaceAll("[\\.|~]","-"));
                    rlistener.addSymbols(symParser.getAlphabet(),
                            (Symbol[])(sl.toList().toArray(new Symbol[0])),
                            0, sl.length());
                } catch (Exception e) {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad sequence",sectionToString(section));
                    throw new ParseException(e, message);
                }
            }
        } while (!sectionKey.equals(END_SEQUENCE_TAG));
        while (true) {
            reader.mark(1);
            int c = reader.read();
            if (c == -1) {
                hasAnotherSequence = false;
                break;
            }
            if (Character.isWhitespace((char) c)) {
                continue;
            }
            reader.reset();
            break;
        }
        rlistener.endSequence();
        return hasAnotherSequence;
    }

    public boolean readRichSequence(BufferedReader reader,
            SymbolTokenization symParser,
            RichSeqIOListener rlistener,
            Namespace ns)
            throws IllegalSymbolException, IOException, ParseException {
        tax = null;
        organism = null;
        accession = null;
        boolean hasAnotherSequence = true;
        rlistener.startSequence();
        if (ns==null) ns=RichObjectFactory.getDefaultNamespace();
        rlistener.setNamespace(ns);
        String sectionKey = null;
        int xrefCount = 0;
        do {
            List section = this.readSection(reader);
            sectionKey = ((String[])section.get(0))[0];
            if(sectionKey == null){
                String message = ParseException.newMessage(this.getClass(), accession, "No section key", "Not set", sectionToString(section));
                throw new ParseException(message);
            }
            if (sectionKey.equals(LOCUS_TAG)) {
                String loc = ((String[])section.get(0))[1];
                Matcher m = lp.matcher(loc);
                Matcher mPre87 = lpPre87.matcher(loc);
                if (m.matches()) {
                    rlistener.setName(m.group(1));
                    rlistener.setAccession(m.group(1));
                    rlistener.setVersion(Integer.parseInt(m.group(2)));
                    rlistener.setCircular(m.group(3).equals("circular"));
                    rlistener.addSequenceProperty(Terms.getMolTypeTerm(),m.group(4));
                    rlistener.addSequenceProperty(Terms.getDataClassTerm(),m.group(5));
                    rlistener.setDivision(m.group(6));
                } else if (mPre87.matches()) {
                    rlistener.setName(mPre87.group(1));
                    if (mPre87.group(3)!=null) {
                        rlistener.addSequenceProperty(Terms.getGenomicTerm(),null);
                    }
                    rlistener.addSequenceProperty(Terms.getMolTypeTerm(),mPre87.group(4));
                    rlistener.setDivision(mPre87.group(5));
                    String circular = mPre87.group(2);
                    if (circular!=null) rlistener.setCircular(true);
                } else {
                    String message = ParseException.newMessage(this.getClass(),accession,"Not Set","Bad ID line found", sectionToString(section));
                    throw new ParseException(message);
                }
            } else if (sectionKey.equals(DEFINITION_TAG)) {
                rlistener.setDescription(((String[])section.get(0))[1]);
            } else if (sectionKey.equals(SOURCE_TAG)) {
                for (int i = 1; i < section.size(); i++) {
                    sectionKey = ((String[])section.get(i))[0];
                    if (sectionKey.equals(ORGANELLE_TAG)) {
                        rlistener.addSequenceProperty(Terms.getOrganelleTerm(), ((String[])section.get(i))[1].trim());
                        break; 
                    }
                }
            } else if (sectionKey.equals(DATE_TAG)) {
                String chunk = ((String[])section.get(0))[1].trim();
                Matcher dm = dp.matcher(chunk);
                if (dm.matches()) {
                    String date = dm.group(1);
                    String rel = dm.group(3);
                    String type = dm.group(4);
                    if (type.equals("Created")) {
                        rlistener.addSequenceProperty(Terms.getDateCreatedTerm(), date);
                        rlistener.addSequenceProperty(Terms.getRelCreatedTerm(), rel);
                    } else if (type.equals("Last updated, Version ")) {
                        rlistener.addSequenceProperty(Terms.getDateUpdatedTerm(), date);
                        rlistener.addSequenceProperty(Terms.getRelUpdatedTerm(), rel);
                    } else {
                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad date type found",sectionToString(section));
                        throw new ParseException(message);
                    }
                } else {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad date line found",sectionToString(section));
                    throw new ParseException(message);
                }
            } else if (sectionKey.equals(ACCESSION_TAG)) {
                String[] accs = ((String[])section.get(0))[1].split(";");
                accession = accs[0].trim();
                rlistener.setAccession(accession);
                for (int i = 1; i < accs.length; i++) {
                    rlistener.addSequenceProperty(Terms.getAdditionalAccessionTerm(),accs[i].trim());
                }
            } else if (sectionKey.equals(VERSION_TAG)) {
                String ver = ((String[])section.get(0))[1];
                Matcher m = vp.matcher(ver);
                if (m.matches()) {
                    String verAcc = m.group(1);
                    if (!accession.equals(verAcc)) {
                        rlistener.addSequenceProperty(Terms.getAdditionalAccessionTerm(),accession);
                        accession = verAcc;
                        rlistener.setAccession(accession);
                    }
                    rlistener.setVersion(Integer.parseInt(m.group(2)));
                } else {
                    rlistener.addSequenceProperty(Terms.getVersionLineTerm(),ver);
                }
            } else if (sectionKey.equals(KEYWORDS_TAG)) {
                String val = ((String[])section.get(0))[1];
                val = val.substring(0,val.length()-1); 
                String[] kws = val.split(";");
                for (int i = 0; i < kws.length; i++) {
                    rlistener.addSequenceProperty(Terms.getKeywordTerm(), kws[i].trim());
                }
            } else if (sectionKey.equals(DATABASE_XREF_TAG)) {
                String val = ((String[])section.get(0))[1];
                val = val.substring(0,val.length()-1); 
                String[] parts = val.split(";");
                CrossRef crossRef = (CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{parts[0].trim(),parts[1].trim(), new Integer(0)});
                for (int j = 2; j < parts.length; j++) {
                    Note note = new SimpleNote(Terms.getAdditionalAccessionTerm(),parts[j].trim(),j-1);
                    try {
                        ((RichAnnotation)crossRef.getAnnotation()).addNote(note);
                    } catch (ChangeVetoException ce) {
                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "Could not annotate identifier terms",sectionToString(section));
                        ParseException pe = new ParseException(message);
                        pe.initCause(ce);
                        throw pe;
                    }
                }
                RankedCrossRef rcrossRef = new SimpleRankedCrossRef(crossRef, ++xrefCount);
                rlistener.setRankedCrossRef(rcrossRef);
            } else if (sectionKey.equals(REFERENCE_TAG) && !this.getElideReferences()) {
                String refrank = ((String[])section.get(0))[1];
                int ref_rank = Integer.parseInt(refrank.substring(1,refrank.length()-1));
                int ref_start = -999;
                int ref_end = -999;
                String consortium = null;
                String authors = null;
                String title = null;
                String locator = null;
                String pubmed = null;
                String medline = null;
                String doi = null;
                String remark = null;
                for (int i = 1; i < section.size(); i++) {
                    String key = ((String[])section.get(i))[0];
                    String val = ((String[])section.get(i))[1];
                    if (key.equals(AUTHORS_TAG)) {
                        if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                        authors = val;
                    }
                    if (key.equals(CONSORTIUM_TAG)) {
                        if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                        consortium = val;
                    }
                    if (key.equals(TITLE_TAG)) {
                        if (val.length()>1) {
                            if (val.endsWith(";")) val = val.substring(0,val.length()-1); 
                            if (val.endsWith("\"")) val = val.substring(1,val.length()-1); 
                            title = val.replace('\n',' '); 
                        } else title=null; 
                    }
                    if (key.equals(LOCATOR_TAG)) {
                        if (val.endsWith(".")) val = val.substring(0,val.length()-1); 
                        locator = val;
                    }
                    if (key.equals(REFERENCE_XREF_TAG)) {
                        String[] refs = val.split("\\.(\\s+|$)");
                        for (int j = 0 ; j < refs.length; j++) {
                            if (refs[j].trim().length()==0) continue;
                            String[] parts = refs[j].split(";");
                            String db = parts[0];
                            String ref = parts[1].trim();
                            if (db.equalsIgnoreCase(Terms.PUBMED_KEY)) pubmed = ref;
                            else if (db.equalsIgnoreCase(Terms.MEDLINE_KEY)) medline = ref;
                            else if (db.equalsIgnoreCase(Terms.DOI_KEY)) doi = ref;
                        }
                    }
                    if (key.equals(REMARK_TAG)) remark = val.replace('\n',' '); 
                    if (key.equals(REFERENCE_POSITION_TAG)) {
                        Matcher m = rpp.matcher(val);
                        if (m.matches()) {
                            ref_start = Integer.parseInt(m.group(1));
                            if(m.group(2) != null)
                                ref_end = Integer.parseInt(m.group(3));
                        } else {
                            String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad reference line found",sectionToString(section));
                            throw new ParseException(message);
                        }
                    }
                }
                try {
                    List authSet = DocRefAuthor.Tools.parseAuthorString(authors);
                    if (consortium!=null) authSet.add(new SimpleDocRefAuthor(consortium, true, false));
                    DocRef dr = (DocRef)RichObjectFactory.getObject(SimpleDocRef.class,new Object[]{authSet,locator,title});
                    if (medline!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.MEDLINE_KEY, medline, new Integer(0)}));
                    else if (pubmed!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.PUBMED_KEY, pubmed, new Integer(0)}));
                    else if (doi!=null) dr.setCrossref((CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{Terms.DOI_KEY, doi, new Integer(0)}));
                    if (!this.getElideComments()) dr.setRemark(remark);
                    RankedDocRef rdr = new SimpleRankedDocRef(dr,
                            (ref_start != -999 ? new Integer(ref_start) : null),
                            (ref_end != -999 ? new Integer(ref_end) : null),
                            ref_rank);
                    rlistener.setRankedDocRef(rdr);
                } catch (ChangeVetoException e) {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                    throw new ParseException(e, message);
                }
            } else if (sectionKey.equals(COMMENT_TAG) && !this.getElideComments()) {
                rlistener.setComment(((String[])section.get(0))[1]);
            } else if (sectionKey.equals(FEATURE_TAG) && !this.getElideFeatures()) {
                boolean seenAFeature = false;
                for (int i = 1 ; i < section.size(); i++) {
                    String key = ((String[])section.get(i))[0];
                    String val = ((String[])section.get(i))[1];
                    if (key.startsWith("/")) {
                        key = key.substring(1); 
                        val = val.replaceAll("\\s*[\\n\\r]+\\s*"," ").trim();
                        if (val.startsWith("\"")) val = val.substring(1,val.length()-1); 
                        if (key.equalsIgnoreCase("db_xref")) {
                            Matcher m = dbxp.matcher(val);
                            if (m.matches()) {
                                String dbname = m.group(1);
                                String raccession = m.group(2);
                                if (dbname.equalsIgnoreCase("taxon")) {
                                    tax = (NCBITaxon)RichObjectFactory.getObject(SimpleNCBITaxon.class, new Object[]{Integer.valueOf(raccession)});
                                    rlistener.setTaxon(tax);
                                    try {
                                        if (organism!=null) tax.addName(NCBITaxon.SCIENTIFIC,organism);
                                    } catch (ChangeVetoException e) {
                                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                        throw new ParseException(e, message);
                                    }
                                } else {
                                    try {
                                        CrossRef cr = (CrossRef)RichObjectFactory.getObject(SimpleCrossRef.class,new Object[]{dbname, raccession, new Integer(0)});
                                        RankedCrossRef rcr = new SimpleRankedCrossRef(cr, 0);
                                        rlistener.getCurrentFeature().addRankedCrossRef(rcr);
                                    } catch (ChangeVetoException e) {
                                        String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                        throw new ParseException(e, message);
                                    }
                                }
                            } else {
                                String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad dbxref found",sectionToString(section));
                                throw new ParseException(message);
                            }
                        } else if (key.equalsIgnoreCase("organism")) {
                            try {
                                organism = val;
                                if (tax!=null) tax.addName(NCBITaxon.SCIENTIFIC,organism);
                            } catch (ChangeVetoException e) {
                                String message = ParseException.newMessage(this.getClass(),accession,"not set", "",sectionToString(section));
                                throw new ParseException(message);
                            }
                        } else {
                            if (key.equalsIgnoreCase("translation")) {
                                val = val.replaceAll("\\s+","");
                            }
                            rlistener.addFeatureProperty(RichObjectFactory.getDefaultOntology().getOrCreateTerm(key),val);
                        }
                    } else {
                        if (seenAFeature) rlistener.endFeature();
                        RichFeature.Template templ = new RichFeature.Template();
                        templ.annotation = new SimpleRichAnnotation();
                        templ.sourceTerm = Terms.getEMBLTerm();
                        templ.typeTerm = RichObjectFactory.getDefaultOntology().getOrCreateTerm(key);
                        templ.featureRelationshipSet = new TreeSet();
                        templ.rankedCrossRefs = new TreeSet();
                        String tidyLocStr = val.replaceAll("\\s+","");
                        templ.location = GenbankLocationParser.parseLocation(ns, accession, tidyLocStr);
                        rlistener.startFeature(templ);
                        seenAFeature = true;
                    }
                }
                if (seenAFeature) rlistener.endFeature();
            } else if (sectionKey.equals(START_SEQUENCE_TAG) && !this.getElideSymbols()) {
                StringBuffer seq = new StringBuffer();
                for (int i = 0 ; i < section.size(); i++) seq.append(((String[])section.get(i))[1]);
                try {
                    SymbolList sl = new SimpleSymbolList(symParser,
                            seq.toString().replaceAll("\\s+","").replaceAll("[\\.|~]","-"));
                    rlistener.addSymbols(symParser.getAlphabet(),
                            (Symbol[])(sl.toList().toArray(new Symbol[0])),
                            0, sl.length());
                } catch (Exception e) {
                    String message = ParseException.newMessage(this.getClass(),accession,"not set", "Bad sequence",sectionToString(section));
                    throw new ParseException(e, message);
                }
            }
        } while (!sectionKey.equals(END_SEQUENCE_TAG));
        while (true) {
            reader.mark(1);
            int c = reader.read();
            if (c == -1) {
                hasAnotherSequence = false;
                break;
            }
            if (Character.isWhitespace((char) c)) {
                continue;
            }
            reader.reset();
            break;
        }
        rlistener.endSequence();
        return hasAnotherSequence;
    }
