ff14b0fe105c6603de37a41a5f8598367e222e42
[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( " " );
108             sb.append( getUnit() );
109         }
110         return sb;
111     }
112
113     @Override
114     public PhylogenyData copy() {
115         return new Property( getRef(), getValue(), getUnit(), getDataType(), getAppliesTo(), getIdRef() );
116     }
117
118     public AppliesTo getAppliesTo() {
119         return _applies_to;
120     }
121
122     public String getDataType() {
123         return _datatype;
124     }
125
126     public String getIdRef() {
127         return _id_ref;
128     }
129
130     public String getRef() {
131         return _ref;
132     }
133
134     public String getUnit() {
135         return _unit;
136     }
137
138     public String getValue() {
139         return _value;
140     }
141
142     @Override
143     public boolean isEqual( final PhylogenyData data ) {
144         if ( data == null ) {
145             return false;
146         }
147         return ( ( Property ) data ).getValue().equals( getValue() )
148                 && ( ( Property ) data ).getUnit().equals( getUnit() )
149                 && ( ( Property ) data ).getRef().equals( getRef() );
150     }
151
152     public void setValue( final String value ) {
153         _value = value;
154     }
155
156     @Override
157     public StringBuffer toNHX() {
158         final StringBuffer nhx = new StringBuffer();
159         nhx.append( ":X" );
160         switch ( getAppliesTo() ) {
161             case CLADE:
162                 nhx.append( "C=" );
163                 break;
164             case NODE:
165                 nhx.append( "N=" );
166                 break;
167             case PARENT_BRANCH:
168                 nhx.append( "B=" );
169                 break;
170             case PHYLOGENY:
171                 nhx.append( "P=" );
172                 break;
173             case ANNOTATION:
174                 nhx.append( "S=" );
175                 break;
176             default:
177                 nhx.append( "O=" );
178                 break;
179         }
180         if ( !getDataType().equals( "" ) ) {
181             if ( getDataType().equals( "xsd:string" ) ) {
182                 nhx.append( "S=" );
183             }
184             else if ( getDataType().equals( "xsd:long" ) ) {
185                 nhx.append( "L=" );
186             }
187             else if ( getDataType().equals( "xsd:decimal" ) ) {
188                 nhx.append( "D=" );
189             }
190             else if ( getDataType().equals( "xsd:boolean" ) ) {
191                 nhx.append( "B=" );
192             }
193             else if ( getDataType().equals( "xsd:anyUR" ) ) {
194                 nhx.append( "U=" );
195             }
196         }
197         nhx.append( getRef() );
198         nhx.append( "=" );
199         nhx.append( getValue() );
200         if ( !getUnit().equals( "" ) ) {
201             nhx.append( "=" );
202             nhx.append( getUnit() );
203         }
204         return nhx;
205     }
206
207     @Override
208     public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
209         PhylogenyDataUtil.appendElement( writer,
210                                          PhyloXmlMapping.PROPERTY,
211                                          getValue(),
212                                          PhyloXmlMapping.PROPERTY_REF,
213                                          getRef(),
214                                          PhyloXmlMapping.PROPERTY_UNIT,
215                                          getUnit(),
216                                          PhyloXmlMapping.PROPERTY_DATATYPE,
217                                          getDataType(),
218                                          PhyloXmlMapping.PROPERTY_APPLIES_TO,
219                                          getAppliesTo().toString(),
220                                          PhyloXmlMapping.ID_REF,
221                                          getIdRef(),
222                                          indentation );
223     }
224
225     @Override
226     public String toString() {
227         return asText().toString();
228     }
229
230     public static Property createFromNhxString( final String nhx ) throws IllegalArgumentException {
231         final StringTokenizer st = new StringTokenizer( nhx, "=" );
232         final int tokens = st.countTokens();
233         final String error = "error in NHX property tag format: "
234                 + "expected: X[N|B|C|S|T|P|O]=<datatype>=<ref>=<value>[=<unit>], got: \"" + nhx + "\" instead";
235         if ( ( tokens != 4 ) && ( tokens != 5 ) ) {
236             throw new IllegalArgumentException( error );
237         }
238         final String first = st.nextToken();
239         AppliesTo applies_to = null;
240         if ( first.equals( "XN" ) ) {
241             applies_to = AppliesTo.NODE;
242         }
243         else if ( first.equals( "XB" ) ) {
244             applies_to = AppliesTo.PARENT_BRANCH;
245         }
246         else if ( first.equals( "XC" ) ) {
247             applies_to = AppliesTo.CLADE;
248         }
249         else if ( first.equals( "XS" ) ) {
250             applies_to = AppliesTo.ANNOTATION;
251         }
252         else if ( first.equals( "XT" ) ) {
253             applies_to = AppliesTo.OTHER;
254         }
255         else if ( first.equals( "XP" ) ) {
256             applies_to = AppliesTo.PHYLOGENY;
257         }
258         else if ( first.equals( "XO" ) ) {
259             applies_to = AppliesTo.OTHER;
260         }
261         else {
262             throw new IllegalArgumentException( error );
263         }
264         String datatype = st.nextToken();
265         if ( datatype.equals( "S" ) ) {
266             datatype = "xsd:string";
267         }
268         else if ( datatype.equals( "L" ) ) {
269             datatype = "xsd:long";
270         }
271         else if ( datatype.equals( "D" ) ) {
272             datatype = "xsd:decimal";
273         }
274         else if ( datatype.equals( "B" ) ) {
275             datatype = "xsd:boolean";
276         }
277         else if ( datatype.equals( "U" ) ) {
278             datatype = "xsd:anyURI";
279         }
280         final String ref = st.nextToken();
281         final String value = st.nextToken();
282         String unit = "";
283         if ( tokens == 5 ) {
284             unit = st.nextToken();
285         }
286         return new Property( ref, value, unit, datatype, applies_to, true );
287     }
288
289     public static enum AppliesTo {
290         PHYLOGENY {
291
292             @Override
293             public String toString() {
294                 return "phylogeny";
295             }
296         },
297         CLADE {
298
299             @Override
300             public String toString() {
301                 return "clade";
302             }
303         },
304         NODE {
305
306             @Override
307             public String toString() {
308                 return "node";
309             }
310         },
311         ANNOTATION {
312
313             @Override
314             public String toString() {
315                 return "annotation";
316             }
317         },
318         PARENT_BRANCH {
319
320             @Override
321             public String toString() {
322                 return "parent_branch";
323             }
324         },
325         OTHER {
326
327             @Override
328             public String toString() {
329                 return "other";
330             }
331         }
332     }
333 }