001package biweekly.io.scribe.property; 002 003import static biweekly.ICalDataType.DATE; 004import static biweekly.ICalDataType.DATE_TIME; 005 006import java.util.ArrayList; 007import java.util.List; 008 009import biweekly.ICalDataType; 010import biweekly.ICalVersion; 011import biweekly.io.CannotParseException; 012import biweekly.io.ParseContext; 013import biweekly.io.WriteContext; 014import biweekly.io.json.JCalValue; 015import biweekly.io.xml.XCalElement; 016import biweekly.parameter.ICalParameters; 017import biweekly.property.ExceptionDates; 018import biweekly.util.ICalDate; 019 020/* 021 Copyright (c) 2013-2015, Michael Angstadt 022 All rights reserved. 023 024 Redistribution and use in source and binary forms, with or without 025 modification, are permitted provided that the following conditions are met: 026 027 1. Redistributions of source code must retain the above copyright notice, this 028 list of conditions and the following disclaimer. 029 2. Redistributions in binary form must reproduce the above copyright notice, 030 this list of conditions and the following disclaimer in the documentation 031 and/or other materials provided with the distribution. 032 033 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 034 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 035 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 036 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 037 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 039 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 040 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 041 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 042 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 043 */ 044 045/** 046 * Marshals {@link ExceptionDates} properties. 047 * @author Michael Angstadt 048 */ 049public class ExceptionDatesScribe extends ListPropertyScribe<ExceptionDates, ICalDate> { 050 public ExceptionDatesScribe() { 051 super(ExceptionDates.class, "EXDATE"); 052 } 053 054 @Override 055 protected ICalDataType _defaultDataType(ICalVersion version) { 056 return DATE_TIME; 057 } 058 059 @Override 060 protected ICalParameters _prepareParameters(ExceptionDates property, WriteContext context) { 061 if (isInObservance(context)) { 062 return property.getParameters(); 063 } 064 065 boolean hasTime; 066 if (property.getValues().isEmpty()) { 067 hasTime = false; 068 } else { 069 hasTime = (dataType(property, context.getVersion()) == DATE_TIME); 070 } 071 return handleTzidParameter(property, hasTime, context); 072 } 073 074 @Override 075 protected ICalDataType _dataType(ExceptionDates property, ICalVersion version) { 076 List<ICalDate> dates = property.getValues(); 077 if (!dates.isEmpty()) { 078 return dates.get(0).hasTime() ? DATE_TIME : DATE; 079 } 080 081 return defaultDataType(version); 082 } 083 084 @Override 085 protected ExceptionDates newInstance(ICalDataType dataType, ICalParameters parameters) { 086 return new ExceptionDates(); 087 } 088 089 @Override 090 protected String writeValue(ExceptionDates property, ICalDate value, WriteContext context) { 091 if (isInObservance(context)) { 092 return date(value).observance(true).extended(false).write(); 093 } 094 095 return date(value, property, context).extended(false).write(); 096 } 097 098 @Override 099 protected ICalDate readValue(ExceptionDates property, String value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 100 ICalDate date; 101 try { 102 boolean hasTime = (dataType == DATE_TIME); 103 date = date(value).hasTime(hasTime).parse(); 104 } catch (IllegalArgumentException e) { 105 throw new CannotParseException(19); 106 } 107 context.addDate(date, property, parameters); 108 109 return date; 110 } 111 112 @Override 113 protected void _writeXml(ExceptionDates property, XCalElement element, WriteContext context) { 114 List<ICalDate> values = property.getValues(); 115 if (values.isEmpty()) { 116 element.append(defaultDataType(context.getVersion()), ""); 117 return; 118 } 119 120 if (isInObservance(context)) { 121 for (ICalDate value : values) { 122 String valueStr = date(value).observance(true).extended(true).write(); 123 element.append(DATE_TIME, valueStr); 124 } 125 return; 126 } 127 128 for (ICalDate value : values) { 129 ICalDataType dataType = value.hasTime() ? DATE_TIME : DATE; 130 String dateStr = date(value, property, context).extended(true).write(); 131 element.append(dataType, dateStr); 132 } 133 } 134 135 @Override 136 protected ExceptionDates _parseXml(XCalElement element, ICalParameters parameters, ParseContext context) { 137 List<String> dateTimeElements = element.all(DATE_TIME); 138 List<String> dateElements = element.all(DATE); 139 if (dateTimeElements.isEmpty() && dateElements.isEmpty()) { 140 throw missingXmlElements(DATE_TIME, DATE); 141 } 142 143 ExceptionDates property = new ExceptionDates(); 144 for (String value : dateTimeElements) { 145 ICalDate datetime = readValue(property, value, DATE_TIME, parameters, context); 146 property.addValue(datetime); 147 } 148 for (String value : dateElements) { 149 ICalDate date = readValue(property, value, DATE, parameters, context); 150 property.addValue(date); 151 } 152 return property; 153 } 154 155 @Override 156 protected JCalValue _writeJson(ExceptionDates property, WriteContext context) { 157 List<ICalDate> values = property.getValues(); 158 if (values.isEmpty()) { 159 return JCalValue.single(""); 160 } 161 162 List<String> valuesStr = new ArrayList<String>(); 163 if (isInObservance(context)) { 164 for (ICalDate value : values) { 165 String valueStr = date(value).observance(true).extended(true).write(); 166 valuesStr.add(valueStr); 167 } 168 return JCalValue.multi(valuesStr); 169 } 170 171 for (ICalDate value : values) { 172 String dateStr = date(value, property, context).extended(true).write(); 173 valuesStr.add(dateStr); 174 } 175 return JCalValue.multi(valuesStr); 176 } 177 178 @Override 179 protected ExceptionDates _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 180 List<String> valueStrs = value.asMulti(); 181 182 ExceptionDates property = new ExceptionDates(); 183 for (String valueStr : valueStrs) { 184 ICalDate date = readValue(property, valueStr, dataType, parameters, context); 185 property.addValue(date); 186 } 187 return property; 188 } 189}