001    package biweekly.property.marshaller;
002    
003    import java.util.List;
004    
005    import biweekly.ICalDataType;
006    import biweekly.Warning;
007    import biweekly.io.CannotParseException;
008    import biweekly.io.json.JCalValue;
009    import biweekly.io.xml.XCalElement;
010    import biweekly.parameter.ICalParameters;
011    import biweekly.property.Geo;
012    import biweekly.util.ICalFloatFormatter;
013    
014    /*
015     Copyright (c) 2013, Michael Angstadt
016     All rights reserved.
017    
018     Redistribution and use in source and binary forms, with or without
019     modification, are permitted provided that the following conditions are met: 
020    
021     1. Redistributions of source code must retain the above copyright notice, this
022     list of conditions and the following disclaimer. 
023     2. Redistributions in binary form must reproduce the above copyright notice,
024     this list of conditions and the following disclaimer in the documentation
025     and/or other materials provided with the distribution. 
026    
027     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
028     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
029     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
030     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
031     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
032     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
033     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
034     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
035     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
036     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037     */
038    
039    /**
040     * Marshals {@link Geo} properties.
041     * @author Michael Angstadt
042     */
043    public class GeoMarshaller extends ICalPropertyMarshaller<Geo> {
044            public GeoMarshaller() {
045                    super(Geo.class, "GEO", ICalDataType.FLOAT);
046            }
047    
048            @Override
049            protected String _writeText(Geo property) {
050                    ICalFloatFormatter formatter = new ICalFloatFormatter();
051                    StringBuilder sb = new StringBuilder();
052    
053                    Double latitude = property.getLatitude();
054                    if (latitude == null) {
055                            latitude = 0.0;
056                    }
057                    sb.append(formatter.format(latitude));
058    
059                    sb.append(';');
060    
061                    Double longitude = property.getLongitude();
062                    if (longitude == null) {
063                            longitude = 0.0;
064                    }
065                    sb.append(formatter.format(longitude));
066    
067                    return sb.toString();
068            }
069    
070            @Override
071            protected Geo _parseText(String value, ICalDataType dataType, ICalParameters parameters, List<Warning> warnings) {
072                    SemiStructuredIterator it = semistructured(value);
073                    String latitudeStr = it.next();
074                    String longitudeStr = it.next();
075    
076                    if (latitudeStr == null || longitudeStr == null) {
077                            throw new CannotParseException(20);
078                    }
079    
080                    return parse(latitudeStr, longitudeStr);
081            }
082    
083            @Override
084            protected void _writeXml(Geo property, XCalElement element) {
085                    ICalFloatFormatter formatter = new ICalFloatFormatter();
086    
087                    Double latitude = property.getLatitude();
088                    if (latitude == null) {
089                            latitude = 0.0;
090                    }
091                    element.append("latitude", formatter.format(latitude));
092    
093                    Double longitude = property.getLongitude();
094                    if (longitude == null) {
095                            longitude = 0.0;
096                    }
097                    element.append("longitude", formatter.format(longitude));
098            }
099    
100            @Override
101            protected Geo _parseXml(XCalElement element, ICalParameters parameters, List<Warning> warnings) {
102                    String latitudeStr = element.first("latitude");
103                    String longitudeStr = element.first("longitude");
104                    if (latitudeStr == null && longitudeStr == null) {
105                            throw missingXmlElements("latitude", "longitude");
106                    }
107                    if (latitudeStr == null) {
108                            throw missingXmlElements("latitude");
109                    }
110                    if (longitudeStr == null) {
111                            throw missingXmlElements("longitude");
112                    }
113    
114                    return parse(latitudeStr, longitudeStr);
115            }
116    
117            @Override
118            protected JCalValue _writeJson(Geo property) {
119                    Double latitude = property.getLatitude();
120                    if (latitude == null) {
121                            latitude = 0.0;
122                    }
123    
124                    Double longitude = property.getLongitude();
125                    if (longitude == null) {
126                            longitude = 0.0;
127                    }
128    
129                    return JCalValue.structured(latitude, longitude);
130            }
131    
132            @Override
133            protected Geo _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, List<Warning> warnings) {
134                    StructuredIterator it = structured(value);
135                    String latitudeStr = it.nextString();
136                    String longitudeStr = it.nextString();
137                    return parse(latitudeStr, longitudeStr);
138            }
139    
140            private Geo parse(String latitudeStr, String longitudeStr) {
141                    Double latitude = null;
142                    if (latitudeStr != null) {
143                            try {
144                                    latitude = Double.valueOf(latitudeStr);
145                            } catch (NumberFormatException e) {
146                                    throw new CannotParseException(21, latitudeStr);
147                            }
148                    }
149    
150                    Double longitude = null;
151                    if (longitudeStr != null) {
152                            try {
153                                    longitude = Double.valueOf(longitudeStr);
154                            } catch (NumberFormatException e) {
155                                    throw new CannotParseException(22, longitudeStr);
156                            }
157                    }
158    
159                    return new Geo(latitude, longitude);
160            }
161    }