001package ezvcard.io.scribe;
002
003import java.util.List;
004
005import com.github.mangstadt.vinnie.io.VObjectPropertyValues;
006
007import ezvcard.VCardDataType;
008import ezvcard.VCardVersion;
009import ezvcard.io.ParseContext;
010import ezvcard.io.html.HCardElement;
011import ezvcard.io.json.JCardValue;
012import ezvcard.io.json.JsonValue;
013import ezvcard.io.text.WriteContext;
014import ezvcard.io.xml.XCardElement;
015import ezvcard.io.xml.XCardElement.XCardValue;
016import ezvcard.parameter.VCardParameters;
017import ezvcard.property.RawProperty;
018
019/*
020 Copyright (c) 2012-2023, Michael Angstadt
021 All rights reserved.
022
023 Redistribution and use in source and binary forms, with or without
024 modification, are permitted provided that the following conditions are met: 
025
026 1. Redistributions of source code must retain the above copyright notice, this
027 list of conditions and the following disclaimer. 
028 2. Redistributions in binary form must reproduce the above copyright notice,
029 this list of conditions and the following disclaimer in the documentation
030 and/or other materials provided with the distribution. 
031
032 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
033 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
034 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
035 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
036 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
037 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
038 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
039 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
040 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
041 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042 */
043
044/**
045 * Marshals {@link RawProperty} properties.
046 * @author Michael Angstadt
047 */
048/*
049 * Note concerning escaping and unescaping special characters:
050 * 
051 * Values are not escaped and unescaped for the following reason: If the
052 * extended property's value is a list or structured list, then the escaping
053 * must be preserved or else escaped special characters will be lost.
054 * 
055 * This is an inconvenience, considering the fact that most extended properties
056 * contain simple text values. But it is necessary in order to prevent data
057 * loss.
058 */
059public class RawPropertyScribe extends VCardPropertyScribe<RawProperty> {
060        public RawPropertyScribe(String propertyName) {
061                super(RawProperty.class, propertyName);
062        }
063
064        @Override
065        protected VCardDataType _defaultDataType(VCardVersion version) {
066                return null;
067        }
068
069        @Override
070        protected VCardDataType _dataType(RawProperty property, VCardVersion version) {
071                return property.getDataType();
072        }
073
074        @Override
075        protected String _writeText(RawProperty property, WriteContext context) {
076                String value = property.getValue();
077                return (value == null) ? "" : value;
078        }
079
080        @Override
081        protected RawProperty _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) {
082                RawProperty property = new RawProperty(propertyName, value);
083                property.setDataType(dataType);
084                return property;
085        }
086
087        @Override
088        protected RawProperty _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) {
089                XCardValue firstValue = element.firstValue();
090                VCardDataType dataType = firstValue.getDataType();
091                String value = firstValue.getValue();
092
093                RawProperty property = new RawProperty(propertyName, value);
094                property.setDataType(dataType);
095                return property;
096        }
097
098        @Override
099        protected RawProperty _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) {
100                String valueStr = jcardValueToString(value);
101
102                RawProperty property = new RawProperty(propertyName, valueStr);
103                property.setDataType(dataType);
104                return property;
105        }
106
107        @Override
108        protected RawProperty _parseHtml(HCardElement element, ParseContext context) {
109                String value = element.value();
110
111                return new RawProperty(propertyName, value);
112        }
113
114        private static String jcardValueToString(JCardValue value) {
115                /*
116                 * VCardPropertyScribe.jcardValueToString() cannot be used because it
117                 * escapes single values.
118                 */
119                List<JsonValue> values = value.getValues();
120                if (values.size() > 1) {
121                        List<String> multi = value.asMulti();
122                        if (!multi.isEmpty()) {
123                                return VObjectPropertyValues.writeList(multi);
124                        }
125                }
126
127                if (!values.isEmpty() && values.get(0).getArray() != null) {
128                        List<List<String>> structured = value.asStructured();
129                        if (!structured.isEmpty()) {
130                                return VObjectPropertyValues.writeStructured(structured, true);
131                        }
132                }
133
134                return value.asSingle();
135        }
136}