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.Warning;
009    import biweekly.io.CannotParseException;
010    import biweekly.io.json.JCalValue;
011    import biweekly.io.xml.XCalElement;
012    import biweekly.parameter.ICalParameters;
013    import biweekly.property.ExceptionDates;
014    
015    /*
016     Copyright (c) 2013, Michael Angstadt
017     All rights reserved.
018    
019     Redistribution and use in source and binary forms, with or without
020     modification, are permitted provided that the following conditions are met: 
021    
022     1. Redistributions of source code must retain the above copyright notice, this
023     list of conditions and the following disclaimer. 
024     2. Redistributions in binary form must reproduce the above copyright notice,
025     this list of conditions and the following disclaimer in the documentation
026     and/or other materials provided with the distribution. 
027    
028     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
029     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
030     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
032     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
034     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
037     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038     */
039    
040    /**
041     * Marshals {@link ExceptionDates} properties.
042     * @author Michael Angstadt
043     */
044    public class ExceptionDatesMarshaller extends ListPropertyMarshaller<ExceptionDates, Date> {
045            public ExceptionDatesMarshaller() {
046                    super(ExceptionDates.class, "EXDATE", ICalDataType.DATE_TIME);
047            }
048    
049            @Override
050            protected ICalDataType _dataType(ExceptionDates property) {
051                    return property.hasTime() ? ICalDataType.DATE_TIME : ICalDataType.DATE;
052            }
053    
054            @Override
055            protected ExceptionDates newInstance(ICalDataType dataType, ICalParameters parameters) {
056                    return new ExceptionDates(dataType != ICalDataType.DATE);
057            }
058    
059            @Override
060            protected String writeValue(ExceptionDates property, Date value) {
061                    return date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).write();
062            }
063    
064            @Override
065            protected Date readValue(String value, ICalDataType dataType, ICalParameters parameters, List<Warning> warnings) {
066                    try {
067                            return date(value).tzid(parameters.getTimezoneId(), warnings).parse();
068                    } catch (IllegalArgumentException e) {
069                            throw new CannotParseException(19);
070                    }
071            }
072    
073            @Override
074            protected void _writeXml(ExceptionDates property, XCalElement element) {
075                    ICalDataType dataType = dataType(property);
076                    for (Date value : property.getValues()) {
077                            String dateStr = date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).extended(true).write();
078                            element.append(dataType, dateStr);
079                    }
080            }
081    
082            @Override
083            protected ExceptionDates _parseXml(XCalElement element, ICalParameters parameters, List<Warning> warnings) {
084                    List<String> values = element.all(ICalDataType.DATE_TIME);
085                    ICalDataType dataType = values.isEmpty() ? ICalDataType.DATE : ICalDataType.DATE_TIME;
086                    values.addAll(element.all(ICalDataType.DATE));
087                    if (values.isEmpty()) {
088                            throw missingXmlElements(ICalDataType.DATE_TIME, ICalDataType.DATE);
089                    }
090    
091                    ExceptionDates prop = new ExceptionDates(dataType == ICalDataType.DATE_TIME);
092                    for (String value : values) {
093                            Date date = readValue(value, dataType, parameters, warnings);
094                            prop.addValue(date);
095                    }
096                    return prop;
097            }
098    
099            @Override
100            protected JCalValue _writeJson(ExceptionDates property) {
101                    List<Date> values = property.getValues();
102                    if (values.isEmpty()) {
103                            return JCalValue.single("");
104                    }
105    
106                    List<String> valuesStr = new ArrayList<String>();
107                    for (Date value : values) {
108                            String dateStr = date(value).time(property.hasTime()).tzid(property.getParameters().getTimezoneId()).extended(true).write();
109                            valuesStr.add(dateStr);
110                    }
111                    return JCalValue.multi(valuesStr);
112            }
113    
114            @Override
115            protected ExceptionDates _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, List<Warning> warnings) {
116                    List<String> valueStrs = value.asMulti();
117    
118                    ExceptionDates prop = new ExceptionDates(dataType == ICalDataType.DATE_TIME);
119                    for (String valueStr : valueStrs) {
120                            Date date = readValue(valueStr, dataType, parameters, warnings);
121                            prop.addValue(date);
122                    }
123                    return prop;
124            }
125    }