001package ezvcard.io.scribe; 002 003import java.time.temporal.Temporal; 004 005import ezvcard.VCardDataType; 006import ezvcard.VCardVersion; 007import ezvcard.io.CannotParseException; 008import ezvcard.io.ParseContext; 009import ezvcard.io.html.HCardElement; 010import ezvcard.io.json.JCardValue; 011import ezvcard.io.text.WriteContext; 012import ezvcard.io.xml.XCardElement; 013import ezvcard.parameter.VCardParameters; 014import ezvcard.property.Revision; 015 016/* 017 Copyright (c) 2012-2023, Michael Angstadt 018 All rights reserved. 019 020 Redistribution and use in source and binary forms, with or without 021 modification, are permitted provided that the following conditions are met: 022 023 1. Redistributions of source code must retain the above copyright notice, this 024 list of conditions and the following disclaimer. 025 2. Redistributions in binary form must reproduce the above copyright notice, 026 this list of conditions and the following disclaimer in the documentation 027 and/or other materials provided with the distribution. 028 029 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 030 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 031 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 032 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 033 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 034 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 035 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 036 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 038 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 039 */ 040 041/** 042 * Marshals {@link Revision} properties. 043 * @author Michael Angstadt 044 */ 045public class RevisionScribe extends VCardPropertyScribe<Revision> { 046 public RevisionScribe() { 047 super(Revision.class, "REV"); 048 } 049 050 @Override 051 protected VCardDataType _defaultDataType(VCardVersion version) { 052 return VCardDataType.TIMESTAMP; 053 } 054 055 @Override 056 protected String _writeText(Revision property, WriteContext context) { 057 boolean extended = (context.getVersion() == VCardVersion.V3_0); 058 return write(property, extended); 059 } 060 061 @Override 062 protected Revision _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 063 return parse(value); 064 } 065 066 @Override 067 protected void _writeXml(Revision property, XCardElement parent) { 068 parent.append(VCardDataType.TIMESTAMP, write(property, false)); 069 } 070 071 @Override 072 protected Revision _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) { 073 String value = element.first(VCardDataType.TIMESTAMP); 074 if (value != null) { 075 return parse(value); 076 } 077 078 throw missingXmlElements(VCardDataType.TIMESTAMP); 079 } 080 081 @Override 082 protected Revision _parseHtml(HCardElement element, ParseContext context) { 083 String value = null; 084 if ("time".equals(element.tagName())) { 085 String datetime = element.attr("datetime"); 086 if (datetime.length() > 0) { 087 value = datetime; 088 } 089 } 090 if (value == null) { 091 value = element.value(); 092 } 093 094 return parse(value); 095 } 096 097 @Override 098 protected JCardValue _writeJson(Revision property) { 099 return JCardValue.single(write(property, true)); 100 } 101 102 @Override 103 protected Revision _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 104 String valueStr = value.asSingle(); 105 return parse(valueStr); 106 } 107 108 private String write(Revision property, boolean extended) { 109 Temporal timestamp = property.getValue(); 110 if (timestamp == null) { 111 return ""; 112 } 113 114 return date(timestamp).extended(extended).write(); 115 } 116 117 private Revision parse(String value) { 118 if (value == null || value.isEmpty()) { 119 return new Revision((Temporal)null); 120 } 121 122 try { 123 return new Revision(date(value)); 124 } catch (IllegalArgumentException e) { 125 throw new CannotParseException(5); 126 } 127 } 128}