// $Id: // FORESTER -- software libraries and applications // for evolutionary biology research and applications. // // Copyright (C) 2008-2009 Christian M. Zmasek // Copyright (C) 2008-2009 Burnham Institute for Medical Research // All rights reserved // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA // // Contact: phylosoft @ gmail . com // WWW: https://sites.google.com/site/cmzmasek/home/software/forester package org.forester.io.parsers.tol; import java.util.ArrayList; import java.util.List; import org.forester.io.parsers.phyloxml.XmlElement; import org.forester.io.parsers.util.PhylogenyParserException; import org.forester.phylogeny.Phylogeny; import org.forester.phylogeny.PhylogenyNode; import org.forester.phylogeny.data.Identifier; import org.forester.phylogeny.data.Taxonomy; import org.forester.util.FailedConditionCheckException; import org.forester.util.ForesterConstants; import org.forester.util.ForesterUtil; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public final class TolXmlHandler extends DefaultHandler { private String _current_element_name; private Phylogeny _current_phylogeny; private List _phylogenies; private XmlElement _current_xml_element; private PhylogenyNode _current_node; private final static StringBuffer _buffer = new StringBuffer(); TolXmlHandler() { // Constructor. } private void addNode() { final PhylogenyNode new_node = new PhylogenyNode(); getCurrentNode().addAsChild( new_node ); setCurrentNode( new_node ); } @Override public void characters( final char[] chars, final int start_index, final int end_index ) { if ( ( ( getCurrentXmlElement() != null ) && ( getCurrentElementName() != null ) ) && !getCurrentElementName().equals( TolXmlMapping.CLADE ) && !getCurrentElementName().equals( TolXmlMapping.PHYLOGENY ) ) { getCurrentXmlElement().setValue( new String( chars, start_index, end_index ).trim() ); } } @Override public void endElement( final String namespace_uri, final String local_name, final String qualified_name ) throws SAXException { if ( ForesterUtil.isEmpty( namespace_uri ) || namespace_uri.startsWith( ForesterConstants.PHYLO_XML_LOCATION ) ) { if ( local_name.equals( TolXmlMapping.CLADE ) ) { try { TolXmlHandler.mapElementToPhylogenyNode( getCurrentXmlElement(), getCurrentNode() ); if ( !getCurrentNode().isRoot() ) { setCurrentNode( getCurrentNode().getParent() ); } setCurrentXmlElement( getCurrentXmlElement().getParent() ); } catch ( final PhylogenyParserException ex ) { throw new SAXException( ex.getMessage() ); } } else if ( local_name.equals( TolXmlMapping.PHYLOGENY ) ) { try { TolXmlHandler.mapElementToPhylogeny( getCurrentXmlElement(), getCurrentPhylogeny() ); } catch ( final PhylogenyParserException ex ) { throw new SAXException( ex.getMessage() ); } finishPhylogeny(); reset(); } else if ( ( getCurrentPhylogeny() != null ) && ( getCurrentXmlElement().getParent() != null ) ) { setCurrentXmlElement( getCurrentXmlElement().getParent() ); } setCurrentElementName( null ); } } private void finishPhylogeny() throws SAXException { getCurrentPhylogeny().setRooted( true ); getCurrentPhylogeny().recalculateNumberOfExternalDescendants( false ); getPhylogenies().add( getCurrentPhylogeny() ); } private String getCurrentElementName() { return _current_element_name; } private PhylogenyNode getCurrentNode() { return _current_node; } private Phylogeny getCurrentPhylogeny() { return _current_phylogeny; } private XmlElement getCurrentXmlElement() { return _current_xml_element; } List getPhylogenies() { return _phylogenies; } private void init() { reset(); setPhylogenies( new ArrayList() ); } private void initCurrentNode() { if ( getCurrentNode() != null ) { throw new FailedConditionCheckException( "attempt to create new current node when current node already exists" ); } if ( getCurrentPhylogeny() == null ) { throw new FailedConditionCheckException( "attempt to create new current node for non-existing phylogeny" ); } final PhylogenyNode node = new PhylogenyNode(); getCurrentPhylogeny().setRoot( node ); setCurrentNode( getCurrentPhylogeny().getRoot() ); } private void newClade() { if ( getCurrentNode() == null ) { initCurrentNode(); } else { addNode(); } } private void newPhylogeny() { setCurrentPhylogeny( new Phylogeny() ); } private void reset() { setCurrentPhylogeny( null ); setCurrentNode( null ); setCurrentElementName( null ); setCurrentXmlElement( null ); } private void setCurrentElementName( final String element_name ) { _current_element_name = element_name; } private void setCurrentNode( final PhylogenyNode current_node ) { _current_node = current_node; } private void setCurrentPhylogeny( final Phylogeny phylogeny ) { _current_phylogeny = phylogeny; } private void setCurrentXmlElement( final XmlElement element ) { _current_xml_element = element; } private void setPhylogenies( final List phylogenies ) { _phylogenies = phylogenies; } @Override public void startDocument() throws SAXException { init(); } @Override public void startElement( final String namespace_uri, final String local_name, final String qualified_name, final Attributes attributes ) throws SAXException { setCurrentElementName( local_name ); if ( local_name.equals( TolXmlMapping.CLADE ) ) { final XmlElement element = new XmlElement( namespace_uri, local_name, local_name, attributes ); getCurrentXmlElement().addChildElement( element ); setCurrentXmlElement( element ); newClade(); } else if ( local_name.equals( TolXmlMapping.PHYLOGENY ) ) { setCurrentXmlElement( new XmlElement( "", "", "", null ) ); newPhylogeny(); } else if ( getCurrentPhylogeny() != null ) { final XmlElement element = new XmlElement( namespace_uri, local_name, local_name, attributes ); getCurrentXmlElement().addChildElement( element ); setCurrentXmlElement( element ); } } public static boolean attributeEqualsValue( final XmlElement element, final String attributeName, final String attributeValue ) { final String attr = element.getAttribute( attributeName ); return ( ( attr != null ) && attr.equals( attributeValue ) ); } public static String getAtttributeValue( final XmlElement element, final String attributeName ) { final String attr = element.getAttribute( attributeName ); if ( attr != null ) { return attr; } else { return ""; } } private static void mapElementToPhylogeny( final XmlElement xml_element, final Phylogeny phylogeny ) throws PhylogenyParserException { // Not needed for now. } private static void mapElementToPhylogenyNode( final XmlElement xml_element, final PhylogenyNode node ) throws PhylogenyParserException { if ( xml_element.isHasAttribute( TolXmlMapping.NODE_ID_ATTR ) ) { final String id = xml_element.getAttribute( TolXmlMapping.NODE_ID_ATTR ); if ( !ForesterUtil.isEmpty( id ) ) { if ( !node.getNodeData().isHasTaxonomy() ) { node.getNodeData().setTaxonomy( new Taxonomy() ); } node.getNodeData().getTaxonomy() .setIdentifier( new Identifier( id, TolXmlMapping.TOL_TAXONOMY_ID_TYPE ) ); } } final boolean put_into_scientific_name = true; // Allways put into scientific name. // if ( xml_element.isHasAttribute( TolXmlMapping.NODE_ITALICIZENAME_ATTR ) ) { // final String ital = xml_element.getAttribute( TolXmlMapping.NODE_ITALICIZENAME_ATTR ); // if ( !ForesterUtil.isEmpty( ital ) && ital.equals( "1" ) ) { // put_into_scientific_name = true; // } // } for( int i = 0; i < xml_element.getNumberOfChildElements(); ++i ) { final XmlElement element = xml_element.getChildElement( i ); final String qualified_name = element.getQualifiedName(); if ( qualified_name.equals( TolXmlMapping.TAXONOMY_NAME ) ) { final String name = element.getValueAsString(); if ( !ForesterUtil.isEmpty( name ) ) { if ( !node.getNodeData().isHasTaxonomy() ) { node.getNodeData().setTaxonomy( new Taxonomy() ); } if ( put_into_scientific_name ) { node.getNodeData().getTaxonomy().setScientificName( name ); } else { node.getNodeData().getTaxonomy().setCommonName( name ); } } } else if ( qualified_name.equals( TolXmlMapping.AUTHORITY ) ) { String auth = element.getValueAsString(); if ( !ForesterUtil.isEmpty( auth ) && !auth.equalsIgnoreCase( "null" ) ) { if ( !node.getNodeData().isHasTaxonomy() ) { node.getNodeData().setTaxonomy( new Taxonomy() ); } auth = auth.replaceAll( "&", "&" ); node.getNodeData().getTaxonomy().setAuthority( auth ); } } else if ( qualified_name.equals( TolXmlMapping.AUTHDATE ) ) { final String authdate = element.getValueAsString(); if ( !ForesterUtil.isEmpty( authdate ) && !authdate.equalsIgnoreCase( "null" ) ) { if ( node.getNodeData().isHasTaxonomy() && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getAuthority() ) ) { _buffer.setLength( 0 ); _buffer.append( node.getNodeData().getTaxonomy().getAuthority() ); _buffer.append( " " ); _buffer.append( authdate ); node.getNodeData().getTaxonomy().setAuthority( _buffer.toString() ); } } } else if ( qualified_name.equals( TolXmlMapping.OTHERNAMES ) ) { for( int j = 0; j < element.getNumberOfChildElements(); ++j ) { final XmlElement element_j = element.getChildElement( j ); if ( element_j.getQualifiedName().equals( TolXmlMapping.OTHERNAME ) ) { for( int z = 0; z < element_j.getNumberOfChildElements(); ++z ) { final XmlElement element_z = element_j.getChildElement( z ); if ( element_z.getQualifiedName().equals( TolXmlMapping.OTHERNAME_NAME ) ) { final String syn = element_z.getValueAsString(); if ( !ForesterUtil.isEmpty( syn ) && !syn.equalsIgnoreCase( "null" ) ) { if ( !node.getNodeData().isHasTaxonomy() ) { node.getNodeData().setTaxonomy( new Taxonomy() ); } node.getNodeData().getTaxonomy().getSynonyms().add( syn ); } } } } } } } } }