in progress
[jalview.git] / forester / java / src / org / forester / phylogeny / data / Property.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 // Copyright (C) 2000-2001 Washington University School of Medicine
8 // and Howard Hughes Medical Institute
9 // All rights reserved
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 //
25 // Contact: phylosoft @ gmail . com
26 // WWW: www.phylosoft.org/forester
27
28 package org.forester.phylogeny.data;
29
30 import java.io.IOException;
31 import java.io.Writer;
32 import java.util.StringTokenizer;
33
34 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
35 import org.forester.util.ForesterUtil;
36
37 public class Property implements PhylogenyData {
38
39     private String          _value;
40     private final String    _ref;
41     private final String    _unit;
42     private final String    _datatype;
43     private final AppliesTo _applies_to;
44     private final String    _id_ref;
45
46     public Property( final String ref,
47                      final String value,
48                      final String unit,
49                      final String datatype,
50                      final AppliesTo applies_to ) {
51         this( ref, value, unit, datatype, applies_to, "" );
52     }
53
54     // Only used by method createFromNhxString.
55     private Property( final String ref,
56                       final String value,
57                       final String unit,
58                       final String datatype,
59                       final AppliesTo applies_to,
60                       final boolean dummy ) {
61         _ref = ref;
62         _unit = unit;
63         _datatype = datatype;
64         _applies_to = applies_to;
65         _id_ref = "";
66         setValue( value );
67     }
68
69     public Property( final String ref,
70                      final String value,
71                      final String unit,
72                      final String datatype,
73                      final AppliesTo applies_to,
74                      final String id_ref ) {
75         if ( !ForesterUtil.isEmpty( ref ) && ( ref.indexOf( ":" ) < 1 ) ) {
76             throw new IllegalArgumentException( "property reference [" + ref
77                     + "] is not in the expected format (missing a \":\")" );
78         }
79         if ( !ForesterUtil.isEmpty( unit ) && ( unit.indexOf( ":" ) < 1 ) ) {
80             throw new IllegalArgumentException( "property unit [" + unit
81                     + "] is not in the expected format (missing a \":\")" );
82         }
83         if ( !ForesterUtil.isEmpty( datatype ) && ( datatype.indexOf( ":" ) < 1 ) ) {
84             throw new IllegalArgumentException( "property datatype [" + unit
85                     + "] is not in the expected format (missing a \":\")" );
86         }
87         _ref = ref;
88         _unit = unit;
89         _datatype = datatype;
90         _applies_to = applies_to;
91         _id_ref = id_ref;
92         setValue( value );
93     }
94
95     @Override
96     public StringBuffer asSimpleText() {
97         return new StringBuffer( getValue() );
98     }
99
100     @Override
101     public StringBuffer asText() {
102         final StringBuffer sb = new StringBuffer();
103         sb.append( getRef() );
104         sb.append( ": " );
105         sb.append( getValue() );
106         if ( !ForesterUtil.isEmpty( getUnit() ) ) {
107             sb.append( getUnit() );
108         }
109         return sb;
110     }
111
112     @Override
113     public PhylogenyData copy() {
114         return new Property( getRef(), getValue(), getUnit(), getDataType(), getAppliesTo(), getIdRef() );
115     }
116
117     public AppliesTo getAppliesTo() {
118         return _applies_to;
119     }
120
121     public String getDataType() {
122         return _datatype;
123     }
124
125     public String getIdRef() {
126         return _id_ref;
127     }
128
129     public String getRef() {
130         return _ref;
131     }
132
133     public String getUnit() {
134         return _unit;
135     }
136
137     public String getValue() {
138         return _value;
139     }
140
141     @Override
142     public boolean isEqual( final PhylogenyData data ) {
143         if ( data == null ) {
144             return false;
145         }
146         return ( ( Property ) data ).getValue().equals( getValue() )
147                 && ( ( Property ) data ).getUnit().equals( getUnit() )
148                 && ( ( Property ) data ).getRef().equals( getRef() );
149     }
150
151     public void setValue( final String value ) {
152         _value = value;
153     }
154
155     @Override
156     public StringBuffer toNHX() {
157         final StringBuffer nhx = new StringBuffer();
158         nhx.append( ":X" );
159         switch ( getAppliesTo() ) {
160             case CLADE:
161                 nhx.append( "C=" );
162                 break;
163             case NODE:
164                 nhx.append( "N=" );
165                 break;
166             case PARENT_BRANCH:
167                 nhx.append( "B=" );
168                 break;
169             case PHYLOGENY:
170                 nhx.append( "P=" );
171                 break;
172             case ANNOTATION:
173                 nhx.append( "S=" );
174                 break;
175             default:
176                 nhx.append( "O=" );
177                 break;
178         }
179         if ( !getDataType().equals( "" ) ) {
180             if ( getDataType().equals( "xsd:string" ) ) {
181                 nhx.append( "S=" );
182             }
183             else if ( getDataType().equals( "xsd:long" ) ) {
184                 nhx.append( "L=" );
185             }
186             else if ( getDataType().equals( "xsd:decimal" ) ) {
187                 nhx.append( "D=" );
188             }
189             else if ( getDataType().equals( "xsd:boolean" ) ) {
190                 nhx.append( "B=" );
191             }
192             else if ( getDataType().equals( "xsd:anyUR" ) ) {
193                 nhx.append( "U=" );
194             }
195         }
196         nhx.append( getRef() );
197         nhx.append( "=" );
198         nhx.append( getValue() );
199         if ( !getUnit().equals( "" ) ) {
200             nhx.append( "=" );
201             nhx.append( getUnit() );
202         }
203         return nhx;
204     }
205
206     @Override
207     public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
208         PhylogenyDataUtil.appendElement( writer,
209                                          PhyloXmlMapping.PROPERTY,
210                                          getValue(),
211                                          PhyloXmlMapping.PROPERTY_REF,
212                                          getRef(),
213                                          PhyloXmlMapping.PROPERTY_UNIT,
214                                          getUnit(),
215                                          PhyloXmlMapping.PROPERTY_DATATYPE,
216                                          getDataType(),
217                                          PhyloXmlMapping.PROPERTY_APPLIES_TO,
218                                          getAppliesTo().toString(),
219                                          PhyloXmlMapping.ID_REF,
220                                          getIdRef(),
221                                          indentation );
222     }
223
224     @Override
225     public String toString() {
226         return asText().toString();
227     }
228
229     public static Property createFromNhxString( final String nhx ) throws IllegalArgumentException {
230         final StringTokenizer st = new StringTokenizer( nhx, "=" );
231         final int tokens = st.countTokens();
232         final String error = "error in NHX property tag format: "
233                 + "expected: X[N|B|C|S|T|P|O]=<datatype>=<ref>=<value>[=<unit>], got: \"" + nhx + "\" instead";
234         if ( ( tokens != 4 ) && ( tokens != 5 ) ) {
235             throw new IllegalArgumentException( error );
236         }
237         final String first = st.nextToken();
238         AppliesTo applies_to = null;
239         if ( first.equals( "XN" ) ) {
240             applies_to = AppliesTo.NODE;
241         }
242         else if ( first.equals( "XB" ) ) {
243             applies_to = AppliesTo.PARENT_BRANCH;
244         }
245         else if ( first.equals( "XC" ) ) {
246             applies_to = AppliesTo.CLADE;
247         }
248         else if ( first.equals( "XS" ) ) {
249             applies_to = AppliesTo.ANNOTATION;
250         }
251         else if ( first.equals( "XT" ) ) {
252             applies_to = AppliesTo.OTHER;
253         }
254         else if ( first.equals( "XP" ) ) {
255             applies_to = AppliesTo.PHYLOGENY;
256         }
257         else if ( first.equals( "XO" ) ) {
258             applies_to = AppliesTo.OTHER;
259         }
260         else {
261             throw new IllegalArgumentException( error );
262         }
263         String datatype = st.nextToken();
264         if ( datatype.equals( "S" ) ) {
265             datatype = "xsd:string";
266         }
267         else if ( datatype.equals( "L" ) ) {
268             datatype = "xsd:long";
269         }
270         else if ( datatype.equals( "D" ) ) {
271             datatype = "xsd:decimal";
272         }
273         else if ( datatype.equals( "B" ) ) {
274             datatype = "xsd:boolean";
275         }
276         else if ( datatype.equals( "U" ) ) {
277             datatype = "xsd:anyURI";
278         }
279         final String ref = st.nextToken();
280         final String value = st.nextToken();
281         String unit = "";
282         if ( tokens == 5 ) {
283             unit = st.nextToken();
284         }
285         return new Property( ref, value, unit, datatype, applies_to, true );
286     }
287
288     public static enum AppliesTo {
289         PHYLOGENY {
290
291             @Override
292             public String toString() {
293                 return "phylogeny";
294             }
295         },
296         CLADE {
297
298             @Override
299             public String toString() {
300                 return "clade";
301             }
302         },
303         NODE {
304
305             @Override
306             public String toString() {
307                 return "node";
308             }
309         },
310         ANNOTATION {
311
312             @Override
313             public String toString() {
314                 return "annotation";
315             }
316         },
317         PARENT_BRANCH {
318
319             @Override
320             public String toString() {
321                 return "parent_branch";
322             }
323         },
324         OTHER {
325
326             @Override
327             public String toString() {
328                 return "other";
329             }
330         }
331     }
332 }