001package ezvcard.io.scribe; 002 003import java.util.List; 004 005import com.github.mangstadt.vinnie.io.VObjectPropertyValues; 006 007import ezvcard.VCard; 008import ezvcard.VCardDataType; 009import ezvcard.VCardVersion; 010import ezvcard.io.ParseContext; 011import ezvcard.io.html.HCardElement; 012import ezvcard.io.json.JCardValue; 013import ezvcard.io.text.WriteContext; 014import ezvcard.io.xml.XCardElement; 015import ezvcard.parameter.VCardParameters; 016import ezvcard.property.Telephone; 017import ezvcard.util.TelUri; 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 Telephone} properties. 046 * @author Michael Angstadt 047 */ 048public class TelephoneScribe extends VCardPropertyScribe<Telephone> { 049 public TelephoneScribe() { 050 super(Telephone.class, "TEL"); 051 } 052 053 @Override 054 protected VCardDataType _defaultDataType(VCardVersion version) { 055 return VCardDataType.TEXT; 056 } 057 058 @Override 059 protected VCardDataType _dataType(Telephone property, VCardVersion version) { 060 if (version == VCardVersion.V4_0) { 061 if (property.getText() != null) { 062 return VCardDataType.TEXT; 063 } 064 if (property.getUri() != null) { 065 return VCardDataType.URI; 066 } 067 } 068 069 return VCardDataType.TEXT; 070 } 071 072 @Override 073 protected void _prepareParameters(Telephone property, VCardParameters copy, VCardVersion version, VCard vcard) { 074 handlePrefParam(property, copy, version, vcard); 075 } 076 077 @Override 078 protected String _writeText(Telephone property, WriteContext context) { 079 String text = property.getText(); 080 if (text != null) { 081 return escape(text, context); 082 } 083 084 TelUri uri = property.getUri(); 085 if (uri != null) { 086 if (context.getVersion() == VCardVersion.V4_0) { 087 return uri.toString(); 088 } 089 090 String ext = uri.getExtension(); 091 String value = (ext == null) ? uri.getNumber() : uri.getNumber() + " x" + ext; 092 return escape(value, context); 093 } 094 095 return ""; 096 } 097 098 @Override 099 protected Telephone _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 100 value = VObjectPropertyValues.unescape(value); 101 return parse(value, dataType, context); 102 } 103 104 @Override 105 protected void _writeXml(Telephone property, XCardElement parent) { 106 String text = property.getText(); 107 if (text != null) { 108 parent.append(VCardDataType.TEXT, text); 109 return; 110 } 111 112 TelUri uri = property.getUri(); 113 if (uri != null) { 114 parent.append(VCardDataType.URI, uri.toString()); 115 return; 116 } 117 118 parent.append(VCardDataType.TEXT, ""); 119 } 120 121 @Override 122 protected Telephone _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) { 123 String text = element.first(VCardDataType.TEXT); 124 if (text != null) { 125 return new Telephone(text); 126 } 127 128 String uri = element.first(VCardDataType.URI); 129 if (uri != null) { 130 try { 131 return new Telephone(TelUri.parse(uri)); 132 } catch (IllegalArgumentException e) { 133 context.addWarning(18); 134 return new Telephone(uri); 135 } 136 } 137 138 throw missingXmlElements(VCardDataType.TEXT, VCardDataType.URI); 139 } 140 141 @Override 142 protected Telephone _parseHtml(HCardElement element, ParseContext context) { 143 Telephone property; 144 String href = element.attr("href"); 145 try { 146 property = new Telephone(TelUri.parse(href)); 147 } catch (IllegalArgumentException e) { 148 //not a tel URI 149 property = new Telephone(element.value()); 150 } 151 152 List<String> types = element.types(); 153 property.getParameters().putAll(VCardParameters.TYPE, types); 154 155 return property; 156 } 157 158 @Override 159 protected JCardValue _writeJson(Telephone property) { 160 String text = property.getText(); 161 if (text != null) { 162 return JCardValue.single(text); 163 } 164 165 TelUri uri = property.getUri(); 166 if (uri != null) { 167 return JCardValue.single(uri.toString()); 168 } 169 170 return JCardValue.single(""); 171 } 172 173 @Override 174 protected Telephone _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 175 String valueStr = value.asSingle(); 176 return parse(valueStr, dataType, context); 177 } 178 179 private Telephone parse(String value, VCardDataType dataType, ParseContext context) { 180 try { 181 return new Telephone(TelUri.parse(value)); 182 } catch (IllegalArgumentException e) { 183 if (dataType == VCardDataType.URI) { 184 context.addWarning(18); 185 } 186 } 187 188 return new Telephone(value); 189 } 190}