(no commit message)
[jalview.git] / forester / java / src / org / forester / io / parsers / tol / TolXmlHandler.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // All rights reserved
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23 // Contact: phylosoft @ gmail . com
24 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
25
26 package org.forester.io.parsers.tol;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import org.forester.io.parsers.phyloxml.XmlElement;
32 import org.forester.io.parsers.util.PhylogenyParserException;
33 import org.forester.phylogeny.Phylogeny;
34 import org.forester.phylogeny.PhylogenyNode;
35 import org.forester.phylogeny.data.Identifier;
36 import org.forester.phylogeny.data.Taxonomy;
37 import org.forester.util.FailedConditionCheckException;
38 import org.forester.util.ForesterConstants;
39 import org.forester.util.ForesterUtil;
40 import org.xml.sax.Attributes;
41 import org.xml.sax.SAXException;
42 import org.xml.sax.helpers.DefaultHandler;
43
44 public final class TolXmlHandler extends DefaultHandler {
45
46     private String                    _current_element_name;
47     private Phylogeny                 _current_phylogeny;
48     private List<Phylogeny>           _phylogenies;
49     private XmlElement                _current_xml_element;
50     private PhylogenyNode             _current_node;
51     private final static StringBuffer _buffer = new StringBuffer();
52
53     TolXmlHandler() {
54         // Constructor.
55     }
56
57     private void addNode() {
58         final PhylogenyNode new_node = new PhylogenyNode();
59         getCurrentNode().addAsChild( new_node );
60         setCurrentNode( new_node );
61     }
62
63     @Override
64     public void characters( final char[] chars, final int start_index, final int end_index ) {
65         if ( ( ( getCurrentXmlElement() != null ) && ( getCurrentElementName() != null ) )
66                 && !getCurrentElementName().equals( TolXmlMapping.CLADE )
67                 && !getCurrentElementName().equals( TolXmlMapping.PHYLOGENY ) ) {
68             getCurrentXmlElement().setValue( new String( chars, start_index, end_index ).trim() );
69         }
70     }
71
72     @Override
73     public void endElement( final String namespace_uri, final String local_name, final String qualified_name )
74             throws SAXException {
75         if ( ForesterUtil.isEmpty( namespace_uri ) || namespace_uri.startsWith( ForesterConstants.PHYLO_XML_LOCATION ) ) {
76             if ( local_name.equals( TolXmlMapping.CLADE ) ) {
77                 try {
78                     TolXmlHandler.mapElementToPhylogenyNode( getCurrentXmlElement(), getCurrentNode() );
79                     if ( !getCurrentNode().isRoot() ) {
80                         setCurrentNode( getCurrentNode().getParent() );
81                     }
82                     setCurrentXmlElement( getCurrentXmlElement().getParent() );
83                 }
84                 catch ( final PhylogenyParserException ex ) {
85                     throw new SAXException( ex.getMessage() );
86                 }
87             }
88             else if ( local_name.equals( TolXmlMapping.PHYLOGENY ) ) {
89                 try {
90                     TolXmlHandler.mapElementToPhylogeny( getCurrentXmlElement(), getCurrentPhylogeny() );
91                 }
92                 catch ( final PhylogenyParserException ex ) {
93                     throw new SAXException( ex.getMessage() );
94                 }
95                 finishPhylogeny();
96                 reset();
97             }
98             else if ( ( getCurrentPhylogeny() != null ) && ( getCurrentXmlElement().getParent() != null ) ) {
99                 setCurrentXmlElement( getCurrentXmlElement().getParent() );
100             }
101             setCurrentElementName( null );
102         }
103     }
104
105     private void finishPhylogeny() throws SAXException {
106         getCurrentPhylogeny().setRooted( true );
107         getCurrentPhylogeny().recalculateNumberOfExternalDescendants( false );
108         getPhylogenies().add( getCurrentPhylogeny() );
109     }
110
111     private String getCurrentElementName() {
112         return _current_element_name;
113     }
114
115     private PhylogenyNode getCurrentNode() {
116         return _current_node;
117     }
118
119     private Phylogeny getCurrentPhylogeny() {
120         return _current_phylogeny;
121     }
122
123     private XmlElement getCurrentXmlElement() {
124         return _current_xml_element;
125     }
126
127     List<Phylogeny> getPhylogenies() {
128         return _phylogenies;
129     }
130
131     private void init() {
132         reset();
133         setPhylogenies( new ArrayList<Phylogeny>() );
134     }
135
136     private void initCurrentNode() {
137         if ( getCurrentNode() != null ) {
138             throw new FailedConditionCheckException( "attempt to create new current node when current node already exists" );
139         }
140         if ( getCurrentPhylogeny() == null ) {
141             throw new FailedConditionCheckException( "attempt to create new current node for non-existing phylogeny" );
142         }
143         final PhylogenyNode node = new PhylogenyNode();
144         getCurrentPhylogeny().setRoot( node );
145         setCurrentNode( getCurrentPhylogeny().getRoot() );
146     }
147
148     private void newClade() {
149         if ( getCurrentNode() == null ) {
150             initCurrentNode();
151         }
152         else {
153             addNode();
154         }
155     }
156
157     private void newPhylogeny() {
158         setCurrentPhylogeny( new Phylogeny() );
159     }
160
161     private void reset() {
162         setCurrentPhylogeny( null );
163         setCurrentNode( null );
164         setCurrentElementName( null );
165         setCurrentXmlElement( null );
166     }
167
168     private void setCurrentElementName( final String element_name ) {
169         _current_element_name = element_name;
170     }
171
172     private void setCurrentNode( final PhylogenyNode current_node ) {
173         _current_node = current_node;
174     }
175
176     private void setCurrentPhylogeny( final Phylogeny phylogeny ) {
177         _current_phylogeny = phylogeny;
178     }
179
180     private void setCurrentXmlElement( final XmlElement element ) {
181         _current_xml_element = element;
182     }
183
184     private void setPhylogenies( final List<Phylogeny> phylogenies ) {
185         _phylogenies = phylogenies;
186     }
187
188     @Override
189     public void startDocument() throws SAXException {
190         init();
191     }
192
193     @Override
194     public void startElement( final String namespace_uri,
195                               final String local_name,
196                               final String qualified_name,
197                               final Attributes attributes ) throws SAXException {
198         setCurrentElementName( local_name );
199         if ( local_name.equals( TolXmlMapping.CLADE ) ) {
200             final XmlElement element = new XmlElement( namespace_uri, local_name, local_name, attributes );
201             getCurrentXmlElement().addChildElement( element );
202             setCurrentXmlElement( element );
203             newClade();
204         }
205         else if ( local_name.equals( TolXmlMapping.PHYLOGENY ) ) {
206             setCurrentXmlElement( new XmlElement( "", "", "", null ) );
207             newPhylogeny();
208         }
209         else if ( getCurrentPhylogeny() != null ) {
210             final XmlElement element = new XmlElement( namespace_uri, local_name, local_name, attributes );
211             getCurrentXmlElement().addChildElement( element );
212             setCurrentXmlElement( element );
213         }
214     }
215
216     public static boolean attributeEqualsValue( final XmlElement element,
217                                                 final String attributeName,
218                                                 final String attributeValue ) {
219         final String attr = element.getAttribute( attributeName );
220         return ( ( attr != null ) && attr.equals( attributeValue ) );
221     }
222
223     public static String getAtttributeValue( final XmlElement element, final String attributeName ) {
224         final String attr = element.getAttribute( attributeName );
225         if ( attr != null ) {
226             return attr;
227         }
228         else {
229             return "";
230         }
231     }
232
233     private static void mapElementToPhylogeny( final XmlElement xml_element, final Phylogeny phylogeny )
234             throws PhylogenyParserException {
235         // Not needed for now.
236     }
237
238     private static void mapElementToPhylogenyNode( final XmlElement xml_element, final PhylogenyNode node )
239             throws PhylogenyParserException {
240         if ( xml_element.isHasAttribute( TolXmlMapping.NODE_ID_ATTR ) ) {
241             final String id = xml_element.getAttribute( TolXmlMapping.NODE_ID_ATTR );
242             if ( !ForesterUtil.isEmpty( id ) ) {
243                 if ( !node.getNodeData().isHasTaxonomy() ) {
244                     node.getNodeData().setTaxonomy( new Taxonomy() );
245                 }
246                 node.getNodeData().getTaxonomy()
247                 .setIdentifier( new Identifier( id, TolXmlMapping.TOL_TAXONOMY_ID_TYPE ) );
248             }
249         }
250         final boolean put_into_scientific_name = true; // Allways put into scientific name.
251         //        if ( xml_element.isHasAttribute( TolXmlMapping.NODE_ITALICIZENAME_ATTR ) ) {
252         //            final String ital = xml_element.getAttribute( TolXmlMapping.NODE_ITALICIZENAME_ATTR );
253         //            if ( !ForesterUtil.isEmpty( ital ) && ital.equals( "1" ) ) {
254         //                put_into_scientific_name = true;
255         //            }
256         //        }
257         for( int i = 0; i < xml_element.getNumberOfChildElements(); ++i ) {
258             final XmlElement element = xml_element.getChildElement( i );
259             final String qualified_name = element.getQualifiedName();
260             if ( qualified_name.equals( TolXmlMapping.TAXONOMY_NAME ) ) {
261                 final String name = element.getValueAsString();
262                 if ( !ForesterUtil.isEmpty( name ) ) {
263                     if ( !node.getNodeData().isHasTaxonomy() ) {
264                         node.getNodeData().setTaxonomy( new Taxonomy() );
265                     }
266                     if ( put_into_scientific_name ) {
267                         node.getNodeData().getTaxonomy().setScientificName( name );
268                     }
269                     else {
270                         node.getNodeData().getTaxonomy().setCommonName( name );
271                     }
272                 }
273             }
274             else if ( qualified_name.equals( TolXmlMapping.AUTHORITY ) ) {
275                 String auth = element.getValueAsString();
276                 if ( !ForesterUtil.isEmpty( auth ) && !auth.equalsIgnoreCase( "null" ) ) {
277                     if ( !node.getNodeData().isHasTaxonomy() ) {
278                         node.getNodeData().setTaxonomy( new Taxonomy() );
279                     }
280                     auth = auth.replaceAll( "&amp;", "&" );
281                     node.getNodeData().getTaxonomy().setAuthority( auth );
282                 }
283             }
284             else if ( qualified_name.equals( TolXmlMapping.AUTHDATE ) ) {
285                 final String authdate = element.getValueAsString();
286                 if ( !ForesterUtil.isEmpty( authdate ) && !authdate.equalsIgnoreCase( "null" ) ) {
287                     if ( node.getNodeData().isHasTaxonomy()
288                             && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getAuthority() ) ) {
289                         _buffer.setLength( 0 );
290                         _buffer.append( node.getNodeData().getTaxonomy().getAuthority() );
291                         _buffer.append( " " );
292                         _buffer.append( authdate );
293                         node.getNodeData().getTaxonomy().setAuthority( _buffer.toString() );
294                     }
295                 }
296             }
297             else if ( qualified_name.equals( TolXmlMapping.OTHERNAMES ) ) {
298                 for( int j = 0; j < element.getNumberOfChildElements(); ++j ) {
299                     final XmlElement element_j = element.getChildElement( j );
300                     if ( element_j.getQualifiedName().equals( TolXmlMapping.OTHERNAME ) ) {
301                         for( int z = 0; z < element_j.getNumberOfChildElements(); ++z ) {
302                             final XmlElement element_z = element_j.getChildElement( z );
303                             if ( element_z.getQualifiedName().equals( TolXmlMapping.OTHERNAME_NAME ) ) {
304                                 final String syn = element_z.getValueAsString();
305                                 if ( !ForesterUtil.isEmpty( syn ) && !syn.equalsIgnoreCase( "null" ) ) {
306                                     if ( !node.getNodeData().isHasTaxonomy() ) {
307                                         node.getNodeData().setTaxonomy( new Taxonomy() );
308                                     }
309                                     node.getNodeData().getTaxonomy().getSynonyms().add( syn );
310                                 }
311                             }
312                         }
313                     }
314                 }
315             }
316         }
317     }
318 }