001package biweekly.io.scribe.property; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import biweekly.ICalDataType; 007import biweekly.io.ParseContext; 008import biweekly.io.WriteContext; 009import biweekly.io.json.JCalValue; 010import biweekly.io.xml.XCalElement; 011import biweekly.parameter.ICalParameters; 012import biweekly.property.ListProperty; 013 014/* 015 Copyright (c) 2013-2015, 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 properties that contain a list of values. 041 * @param <T> the property class 042 * @param <V> the value class 043 * @author Michael Angstadt 044 */ 045public abstract class ListPropertyScribe<T extends ListProperty<V>, V> extends ICalPropertyScribe<T> { 046 public ListPropertyScribe(Class<T> clazz, String propertyName) { 047 this(clazz, propertyName, ICalDataType.TEXT); 048 } 049 050 public ListPropertyScribe(Class<T> clazz, String propertyName, ICalDataType dataType) { 051 super(clazz, propertyName, dataType); 052 } 053 054 @Override 055 protected String _writeText(final T property, WriteContext context) { 056 List<V> values = property.getValues(); 057 List<String> valuesStr = new ArrayList<String>(values.size()); 058 for (V value : values) { 059 String valueStr = writeValue(property, value, context); 060 valuesStr.add(valueStr); 061 } 062 063 switch (context.getVersion()) { 064 case V1_0: 065 Object[] valuesArray = valuesStr.toArray(new String[0]); 066 return structured(valuesArray); 067 default: 068 return list(valuesStr); 069 } 070 } 071 072 @Override 073 protected T _parseText(String value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 074 List<String> values; 075 switch (context.getVersion()) { 076 case V1_0: 077 values = new ArrayList<String>(); 078 if (value.length() > 0) { 079 SemiStructuredIterator it = semistructured(value); 080 while (it.hasNext()) { 081 values.add(it.next()); 082 } 083 } 084 break; 085 086 default: 087 values = list(value); 088 } 089 090 return parse(values, dataType, parameters, context); 091 } 092 093 @Override 094 protected void _writeXml(T property, XCalElement element, WriteContext context) { 095 for (V value : property.getValues()) { 096 String valueStr = writeValue(property, value, null); 097 element.append(dataType(property, null), valueStr); 098 } 099 } 100 101 @Override 102 protected T _parseXml(XCalElement element, ICalParameters parameters, ParseContext context) { 103 ICalDataType dataType = defaultDataType(context.getVersion()); 104 List<String> values = element.all(dataType); 105 if (!values.isEmpty()) { 106 return parse(values, dataType, parameters, context); 107 } 108 109 throw missingXmlElements(dataType); 110 } 111 112 @Override 113 protected JCalValue _writeJson(T property, WriteContext context) { 114 List<V> values = property.getValues(); 115 if (!values.isEmpty()) { 116 return JCalValue.multi(property.getValues()); 117 } 118 119 return JCalValue.single(""); 120 } 121 122 @Override 123 protected T _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 124 return parse(value.asMulti(), dataType, parameters, context); 125 } 126 127 private T parse(List<String> valueStrs, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 128 T property = newInstance(dataType, parameters); 129 130 for (String valueStr : valueStrs) { 131 V value = readValue(property, valueStr, dataType, parameters, context); 132 property.addValue(value); 133 } 134 135 return property; 136 } 137 138 protected abstract T newInstance(ICalDataType dataType, ICalParameters parameters); 139 140 protected abstract String writeValue(T property, V value, WriteContext context); 141 142 protected abstract V readValue(T property, String value, ICalDataType dataType, ICalParameters parameters, ParseContext context); 143}