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