2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
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
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.
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.
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
25 // Contact: phylosoft @ gmail . com
26 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
28 package org.forester.phylogeny.data;
30 import java.io.IOException;
31 import java.io.Writer;
32 import java.util.StringTokenizer;
34 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
35 import org.forester.util.ForesterUtil;
37 public class Property implements PhylogenyData {
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;
46 public Property( final String ref,
49 final String datatype,
50 final AppliesTo applies_to ) {
51 this( ref, value, unit, datatype, applies_to, "" );
54 // Only used by method createFromNhxString.
55 private Property( final String ref,
58 final String datatype,
59 final AppliesTo applies_to,
60 final boolean dummy ) {
64 _applies_to = applies_to;
69 public Property( final String ref,
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 \":\")" );
79 if ( !ForesterUtil.isEmpty( unit ) && ( unit.indexOf( ":" ) < 1 ) ) {
80 throw new IllegalArgumentException( "property unit [" + unit
81 + "] is not in the expected format (missing a \":\")" );
83 if ( !ForesterUtil.isEmpty( datatype ) && ( datatype.indexOf( ":" ) < 1 ) ) {
84 throw new IllegalArgumentException( "property datatype [" + unit
85 + "] is not in the expected format (missing a \":\")" );
90 _applies_to = applies_to;
96 public StringBuffer asSimpleText() {
97 return new StringBuffer( getValue() );
101 public StringBuffer asText() {
102 final StringBuffer sb = new StringBuffer();
103 sb.append( getRef() );
105 sb.append( getValue() );
106 if ( !ForesterUtil.isEmpty( getUnit() ) ) {
108 sb.append( getUnit() );
114 public PhylogenyData copy() {
115 return new Property( getRef(), getValue(), getUnit(), getDataType(), getAppliesTo(), getIdRef() );
118 public AppliesTo getAppliesTo() {
122 public String getDataType() {
126 public String getIdRef() {
130 public String getRef() {
134 public String getUnit() {
138 public String getValue() {
143 public boolean isEqual( final PhylogenyData data ) {
144 if ( data == null ) {
147 return ( ( Property ) data ).getValue().equals( getValue() )
148 && ( ( Property ) data ).getUnit().equals( getUnit() )
149 && ( ( Property ) data ).getRef().equals( getRef() );
152 public void setValue( final String value ) {
157 public StringBuffer toNHX() {
158 final StringBuffer nhx = new StringBuffer();
160 switch ( getAppliesTo() ) {
180 if ( !getDataType().equals( "" ) ) {
181 if ( getDataType().equals( "xsd:string" ) ) {
184 else if ( getDataType().equals( "xsd:long" ) ) {
187 else if ( getDataType().equals( "xsd:decimal" ) ) {
190 else if ( getDataType().equals( "xsd:boolean" ) ) {
193 else if ( getDataType().equals( "xsd:anyUR" ) ) {
197 nhx.append( getRef() );
199 nhx.append( getValue() );
200 if ( !getUnit().equals( "" ) ) {
202 nhx.append( getUnit() );
208 public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
209 PhylogenyDataUtil.appendElement( writer,
210 PhyloXmlMapping.PROPERTY,
212 PhyloXmlMapping.PROPERTY_REF,
214 PhyloXmlMapping.PROPERTY_UNIT,
216 PhyloXmlMapping.PROPERTY_DATATYPE,
218 PhyloXmlMapping.PROPERTY_APPLIES_TO,
219 getAppliesTo().toString(),
220 PhyloXmlMapping.ID_REF,
226 public String toString() {
227 return asText().toString();
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 );
238 final String first = st.nextToken();
239 AppliesTo applies_to = null;
240 if ( first.equals( "XN" ) ) {
241 applies_to = AppliesTo.NODE;
243 else if ( first.equals( "XB" ) ) {
244 applies_to = AppliesTo.PARENT_BRANCH;
246 else if ( first.equals( "XC" ) ) {
247 applies_to = AppliesTo.CLADE;
249 else if ( first.equals( "XS" ) ) {
250 applies_to = AppliesTo.ANNOTATION;
252 else if ( first.equals( "XT" ) ) {
253 applies_to = AppliesTo.OTHER;
255 else if ( first.equals( "XP" ) ) {
256 applies_to = AppliesTo.PHYLOGENY;
258 else if ( first.equals( "XO" ) ) {
259 applies_to = AppliesTo.OTHER;
262 throw new IllegalArgumentException( error );
264 String datatype = st.nextToken();
265 if ( datatype.equals( "S" ) ) {
266 datatype = "xsd:string";
268 else if ( datatype.equals( "L" ) ) {
269 datatype = "xsd:long";
271 else if ( datatype.equals( "D" ) ) {
272 datatype = "xsd:decimal";
274 else if ( datatype.equals( "B" ) ) {
275 datatype = "xsd:boolean";
277 else if ( datatype.equals( "U" ) ) {
278 datatype = "xsd:anyURI";
280 final String ref = st.nextToken();
281 final String value = st.nextToken();
284 unit = st.nextToken();
286 return new Property( ref, value, unit, datatype, applies_to, true );
289 public static enum AppliesTo {
293 public String toString() {
300 public String toString() {
307 public String toString() {
314 public String toString() {
321 public String toString() {
322 return "parent_branch";
328 public String toString() {