001    package biweekly.property.marshaller;
002    
003    import java.util.ArrayList;
004    import java.util.Date;
005    import java.util.List;
006    
007    import biweekly.ICalDataType;
008    import biweekly.io.CannotParseException;
009    import biweekly.io.json.JCalValue;
010    import biweekly.io.xml.XCalElement;
011    import biweekly.parameter.ICalParameters;
012    import biweekly.property.ExceptionDates;
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 ExceptionDates} properties.
041     * @author Michael Angstadt
042     */
043    public class ExceptionDatesMarshaller extends ListPropertyMarshaller<ExceptionDates, Date> {
044            public ExceptionDatesMarshaller() {
045                    super(ExceptionDates.class, "EXDATE", ICalDataType.DATE_TIME);
046            }
047    
048            @Override
049            protected ICalDataType _dataType(ExceptionDates property) {
050                    return property.hasTime() ? ICalDataType.DATE_TIME : ICalDataType.DATE;
051            }
052    
053            @Override
054            protected ExceptionDates newInstance(ICalDataType dataType, ICalParameters parameters) {
055                    return new ExceptionDates(dataType != ICalDataType.DATE);
056            }
057    
058            @Override
059            protected String writeValue(ExceptionDates property, Date value) {
060                    return date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).write();
061            }
062    
063            @Override
064            protected Date readValue(String value, ICalDataType dataType, ICalParameters parameters, List<String> warnings) {
065                    try {
066                            return date(value).tzid(parameters.getTimezoneId(), warnings).parse();
067                    } catch (IllegalArgumentException e) {
068                            throw new CannotParseException("Could not parse date value.");
069                    }
070            }
071    
072            @Override
073            protected void _writeXml(ExceptionDates property, XCalElement element) {
074                    ICalDataType dataType = dataType(property);
075                    for (Date value : property.getValues()) {
076                            String dateStr = date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).extended(true).write();
077                            element.append(dataType, dateStr);
078                    }
079            }
080    
081            @Override
082            protected ExceptionDates _parseXml(XCalElement element, ICalParameters parameters, List<String> warnings) {
083                    List<String> values = element.all(ICalDataType.DATE_TIME);
084                    ICalDataType dataType = values.isEmpty() ? ICalDataType.DATE : ICalDataType.DATE_TIME;
085                    values.addAll(element.all(ICalDataType.DATE));
086                    if (values.isEmpty()) {
087                            throw missingXmlElements(ICalDataType.DATE_TIME, ICalDataType.DATE);
088                    }
089    
090                    ExceptionDates prop = new ExceptionDates(dataType == ICalDataType.DATE_TIME);
091                    for (String value : values) {
092                            Date date = readValue(value, dataType, parameters, warnings);
093                            prop.addValue(date);
094                    }
095                    return prop;
096            }
097    
098            @Override
099            protected JCalValue _writeJson(ExceptionDates property) {
100                    List<Date> values = property.getValues();
101                    if (values.isEmpty()) {
102                            return JCalValue.single("");
103                    }
104    
105                    List<String> valuesStr = new ArrayList<String>();
106                    for (Date value : values) {
107                            String dateStr = date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).extended(true).write();
108                            valuesStr.add(dateStr);
109                    }
110                    return JCalValue.multi(valuesStr);
111            }
112    
113            @Override
114            protected ExceptionDates _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, List<String> warnings) {
115                    List<String> valueStrs = value.asMulti();
116    
117                    ExceptionDates prop = new ExceptionDates(dataType == ICalDataType.DATE_TIME);
118                    for (String valueStr : valueStrs) {
119                            Date date = readValue(valueStr, dataType, parameters, warnings);
120                            prop.addValue(date);
121                    }
122                    return prop;
123            }
124    }