001package ezvcard; 002 003import static ezvcard.VCardVersion.V2_1; 004import static ezvcard.VCardVersion.V3_0; 005import static ezvcard.VCardVersion.V4_0; 006 007import java.lang.reflect.Field; 008import java.lang.reflect.Modifier; 009import java.util.Collection; 010 011import ezvcard.util.CaseClasses; 012 013/* 014 Copyright (c) 2012-2023, Michael Angstadt 015 All rights reserved. 016 017 Redistribution and use in source and binary forms, with or without 018 modification, are permitted provided that the following conditions are met: 019 020 1. Redistributions of source code must retain the above copyright notice, this 021 list of conditions and the following disclaimer. 022 2. Redistributions in binary form must reproduce the above copyright notice, 023 this list of conditions and the following disclaimer in the documentation 024 and/or other materials provided with the distribution. 025 026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 029 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 030 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 031 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 032 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 033 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 034 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 035 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 036 037 The views and conclusions contained in the software and documentation are those 038 of the authors and should not be interpreted as representing official policies, 039 either expressed or implied, of the FreeBSD Project. 040 */ 041 042/** 043 * Defines the data type of a property's value. 044 * @author Michael Angstadt 045 */ 046public class VCardDataType { 047 private static final CaseClasses<VCardDataType, String> enums = new CaseClasses<VCardDataType, String>(VCardDataType.class) { 048 @Override 049 protected VCardDataType create(String value) { 050 return new VCardDataType(value); 051 } 052 053 @Override 054 protected boolean matches(VCardDataType dataType, String value) { 055 return dataType.name.equalsIgnoreCase(value); 056 } 057 }; 058 059 /** 060 * A uniform resource locator (for example, 061 * "http://www.example.com/image.jpg"). This data type is only used in 2.1 062 * vCards. All other vCard versions use {@link #URI}. 063 */ 064 @SupportedVersions(V2_1) 065 public static final VCardDataType URL = new VCardDataType("url"); 066 067 /** 068 * Refers to a MIME entity within an email. 069 */ 070 @SupportedVersions(V2_1) 071 public static final VCardDataType CONTENT_ID = new VCardDataType("content-id"); 072 073 /** 074 * A non-textual value, such as a picture or sound file. 075 */ 076 @SupportedVersions(V3_0) 077 public static final VCardDataType BINARY = new VCardDataType("binary"); 078 079 /** 080 * A uniform resource identifier (for example, 081 * "http://www.example.com/image.jpg"). 2.1 vCards use {@link #URL} instead. 082 */ 083 @SupportedVersions({ V3_0, V4_0 }) 084 public static final VCardDataType URI = new VCardDataType("uri"); 085 086 /** 087 * A plain text value. 088 */ 089 public static final VCardDataType TEXT = new VCardDataType("text"); 090 091 /** 092 * A date that does not have a time component (for example, "2015-02-16"). 093 */ 094 @SupportedVersions({ V3_0, V4_0 }) 095 public static final VCardDataType DATE = new VCardDataType("date"); 096 097 /** 098 * A time that does not have a date component (for example, "08:34:00"). 099 */ 100 @SupportedVersions({ V3_0, V4_0 }) 101 public static final VCardDataType TIME = new VCardDataType("time"); 102 103 /** 104 * A date with a time component (for example, "2015-02-16 08:34:00"). 105 */ 106 @SupportedVersions({ V3_0, V4_0 }) 107 public static final VCardDataType DATE_TIME = new VCardDataType("date-time"); 108 109 /** 110 * Any sort of date/time combination. The value can be a date (e.g. 111 * "2015-02-16"), a time (e.g. "08:34:00"), or a date with a time component 112 * (e.g. "2015-02-16 08:34:00"). 113 */ 114 @SupportedVersions(V4_0) 115 public static final VCardDataType DATE_AND_OR_TIME = new VCardDataType("date-and-or-time"); 116 117 /** 118 * A specific moment in time. Timestamps should be in UTC time. 119 */ 120 @SupportedVersions(V4_0) 121 public static final VCardDataType TIMESTAMP = new VCardDataType("timestamp"); 122 123 /** 124 * A boolean value ("true" or "false"). 125 */ 126 @SupportedVersions(V4_0) 127 public static final VCardDataType BOOLEAN = new VCardDataType("boolean"); 128 129 /** 130 * An integer value (for example, "42"). 131 */ 132 @SupportedVersions(V4_0) 133 public static final VCardDataType INTEGER = new VCardDataType("integer"); 134 135 /** 136 * A floating-point value (for example, "3.14"). 137 */ 138 @SupportedVersions(V4_0) 139 public static final VCardDataType FLOAT = new VCardDataType("float"); 140 141 /** 142 * An offset from UTC time, in hours and minutes (for example, "-0500"). 143 */ 144 @SupportedVersions(V4_0) 145 public static final VCardDataType UTC_OFFSET = new VCardDataType("utc-offset"); 146 147 /** 148 * A standardized abbreviation for a language (for example, "en-us" for 149 * American English). 150 * @see <a href="http://tools.ietf.org/html/rfc5646">RFC 5646</a> 151 */ 152 @SupportedVersions(V4_0) 153 public static final VCardDataType LANGUAGE_TAG = new VCardDataType("language-tag"); 154 155 private final String name; 156 157 /** 158 * @param name the data type name 159 */ 160 private VCardDataType(String name) { 161 this.name = name; 162 } 163 164 /** 165 * Gets the name of the data type. 166 * @return the name of the data type (e.g. "text") 167 */ 168 public String getName() { 169 return name; 170 } 171 172 /** 173 * <p> 174 * Gets the vCard versions that support this data type. 175 * </p> 176 * <p> 177 * The supported versions are defined by assigning a 178 * {@link SupportedVersions} annotation to the data type's static field (for 179 * example, {@link VCardDataType#CONTENT_ID}). Dynamically-created data 180 * types (i.e. non-standard data types) are considered to be supported by 181 * all versions. 182 * </p> 183 * @return the vCard versions that support this data type 184 */ 185 public VCardVersion[] getSupportedVersions() { 186 for (Field field : getClass().getFields()) { 187 if (!Modifier.isStatic(field.getModifiers())) { 188 continue; 189 } 190 191 Object fieldValue; 192 try { 193 fieldValue = field.get(null); 194 } catch (IllegalArgumentException e) { 195 //should never be thrown because we check for the static modified 196 continue; 197 } catch (IllegalAccessException e) { 198 continue; 199 } 200 201 if (fieldValue == this) { 202 SupportedVersions supportedVersionsAnnotation = field.getAnnotation(SupportedVersions.class); 203 return (supportedVersionsAnnotation == null) ? VCardVersion.values() : supportedVersionsAnnotation.value(); 204 } 205 } 206 207 return VCardVersion.values(); 208 } 209 210 /** 211 * <p> 212 * Determines if this data type is supported by the given vCard version. 213 * </p> 214 * <p> 215 * The supported versions are defined by assigning a 216 * {@link SupportedVersions} annotation to the data type's static field (for 217 * example, {@link VCardDataType#CONTENT_ID}). Dynamically-created data 218 * types (i.e. non-standard data types) are considered to be supported by 219 * all versions. 220 * </p> 221 * @param version the vCard version 222 * @return true if it is supported, false if not 223 */ 224 public boolean isSupportedBy(VCardVersion version) { 225 for (VCardVersion supportedVersion : getSupportedVersions()) { 226 if (supportedVersion == version) { 227 return true; 228 } 229 } 230 return false; 231 } 232 233 @Override 234 public String toString() { 235 return name; 236 } 237 238 /** 239 * Searches for a data type that is defined as a static constant in this 240 * class. 241 * @param dataType the data type name (e.g. "text") 242 * @return the data type or null if not found 243 */ 244 public static VCardDataType find(String dataType) { 245 return enums.find(dataType); 246 } 247 248 /** 249 * Searches for a data type and creates one if it cannot be found. All 250 * objects are guaranteed to be unique, so they can be compared with 251 * {@code ==} equality. 252 * @param dataType data type name (e.g. "text") 253 * @return the data type 254 */ 255 public static VCardDataType get(String dataType) { 256 return enums.get(dataType); 257 } 258 259 /** 260 * Gets all of the data types that are defined as static constants in this 261 * class. 262 * @return the data types 263 */ 264 public static Collection<VCardDataType> all() { 265 return enums.all(); 266 } 267 268 /* 269 * Note: This class doesn't need equals() or hashCode() because the 270 * CaseClasses object enforces reference equality. 271 */ 272 273 @Override 274 public int hashCode() { 275 return super.hashCode(); 276 } 277 278 @Override 279 public boolean equals(Object obj) { 280 return super.equals(obj); 281 } 282}