001 package ezvcard.property; 002 003 import java.util.ArrayList; 004 import java.util.Arrays; 005 import java.util.EnumSet; 006 import java.util.List; 007 import java.util.Set; 008 009 import ezvcard.VCard; 010 import ezvcard.VCardVersion; 011 import ezvcard.Warning; 012 import ezvcard.parameter.VCardParameters; 013 014 /* 015 Copyright (c) 2013, 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 The views and conclusions contained in the software and documentation are those 039 of the authors and should not be interpreted as representing official policies, 040 either expressed or implied, of the FreeBSD Project. 041 */ 042 043 /** 044 * Represents a vCard key/value pair entry (called a "type" or "property"). 045 * @author Michael Angstadt 046 */ 047 public abstract class VCardProperty implements Comparable<VCardProperty> { 048 /** 049 * The group that this property belongs to or null if it doesn't belong to a 050 * group. 051 */ 052 protected String group; 053 054 /** 055 * The property's parameters. 056 */ 057 protected VCardParameters parameters = new VCardParameters(); 058 059 /** 060 * Gets the vCard versions that support this property. 061 * @return the vCard versions that support this property. 062 */ 063 public final Set<VCardVersion> getSupportedVersions() { 064 return _supportedVersions(); 065 } 066 067 /** 068 * <p> 069 * Gets the vCard versions that support this property. 070 * </p> 071 * <p> 072 * This method should be overridden by child classes if the property does 073 * not support all vCard versions. The default implementation of this method 074 * returns all vCard versions. 075 * </p> 076 * @return the vCard versions that support this property. 077 */ 078 protected Set<VCardVersion> _supportedVersions() { 079 return EnumSet.copyOf(Arrays.asList(VCardVersion.values())); 080 } 081 082 /** 083 * Checks the property for data consistency problems or deviations from the 084 * spec. These problems will not prevent the property from being written to 085 * a data stream, but may prevent it from being parsed correctly by the 086 * consuming application. These problems can largely be avoided by reading 087 * the Javadocs of the property class, or by being familiar with the vCard 088 * standard. 089 * @param version the version to check the property against (use 4.0 for 090 * xCard and jCard) 091 * @param vcard the vCard this property belongs to 092 * @see VCard#validate 093 * @return a list of warnings or an empty list if no problems were found 094 */ 095 public final List<Warning> validate(VCardVersion version, VCard vcard) { 096 List<Warning> warnings = new ArrayList<Warning>(0); 097 098 //check the supported versions 099 Set<VCardVersion> supportedVersions = getSupportedVersions(); 100 if (!supportedVersions.contains(version)) { 101 warnings.add(new Warning(2, supportedVersions)); 102 } 103 104 //check parameters 105 warnings.addAll(parameters.validate(version)); 106 107 _validate(warnings, version, vcard); 108 109 return warnings; 110 } 111 112 /** 113 * Checks the property for data consistency problems or deviations from the 114 * spec. Meant to be overridden by child classes that wish to provide 115 * validation logic. 116 * @param warnings the list to add the warnings to 117 * @param version the version to check the property against 118 * @param vcard the vCard this property belongs to 119 */ 120 protected void _validate(List<Warning> warnings, VCardVersion version, VCard vcard) { 121 //empty 122 } 123 124 /** 125 * Gets all of the property's parameters. 126 * @return the property's parameters 127 */ 128 public VCardParameters getParameters() { 129 return parameters; 130 } 131 132 /** 133 * Sets the property's parameters. 134 * @param parameters the parameters 135 */ 136 public void setParameters(VCardParameters parameters) { 137 this.parameters = parameters; 138 } 139 140 /** 141 * Gets the first value of a parameter. 142 * @param name the parameter name (case insensitive, e.g. "LANGUAGE") 143 * @return the parameter value or null if not found 144 */ 145 public String getParameter(String name) { 146 return parameters.first(name); 147 } 148 149 /** 150 * Gets all values of a parameter. 151 * @param name the parameter name (case insensitive, e.g. "LANGUAGE") 152 * @return the parameter values 153 */ 154 public List<String> getParameters(String name) { 155 return parameters.get(name); 156 } 157 158 /** 159 * Replaces all existing values of a parameter with the given value. 160 * @param name the parameter name (case insensitive, e.g. "LANGUAGE") 161 * @param value the parameter value 162 */ 163 public void setParameter(String name, String value) { 164 parameters.replace(name, value); 165 } 166 167 /** 168 * Adds a value to a parameter. 169 * @param name the parameter name (case insensitive, e.g. "LANGUAGE") 170 * @param value the parameter value 171 */ 172 public void addParameter(String name, String value) { 173 parameters.put(name, value); 174 } 175 176 /** 177 * Removes a parameter from the property. 178 * @param name the parameter name (case insensitive, e.g. "LANGUAGE") 179 */ 180 public void removeParameter(String name) { 181 parameters.removeAll(name); 182 } 183 184 /** 185 * Gets this property's group. 186 * @return the group or null if it does not belong to a group 187 */ 188 public String getGroup() { 189 return group; 190 } 191 192 /** 193 * Sets this property's group. 194 * @param group the group or null to remove the property's group 195 */ 196 public void setGroup(String group) { 197 this.group = group; 198 } 199 200 /** 201 * Sorts by PREF parameter ascending. Properties that do not have a PREF 202 * parameter are pushed to the end of the list. 203 */ 204 public int compareTo(VCardProperty that) { 205 Integer pref0 = this.getParameters().getPref(); 206 Integer pref1 = that.getParameters().getPref(); 207 if (pref0 == null && pref1 == null) { 208 return 0; 209 } 210 if (pref0 == null) { 211 return 1; 212 } 213 if (pref1 == null) { 214 return -1; 215 } 216 return pref1.compareTo(pref0); 217 } 218 219 //Note: The following parameter helper methods are package-scoped to prevent them from cluttering up the Javadocs 220 221 /** 222 * <p> 223 * Gets all PID values. 224 * </p> 225 * <p> 226 * <b>Supported versions:</b> {@code 4.0} 227 * </p> 228 * @return the PID values or empty set if there are none 229 * @see VCardParameters#getPids 230 */ 231 List<Integer[]> getPids() { 232 return parameters.getPids(); 233 } 234 235 /** 236 * <p> 237 * Adds a PID value. 238 * </p> 239 * <p> 240 * <b>Supported versions:</b> {@code 4.0} 241 * </p> 242 * @param localId the local ID 243 * @param clientPidMapRef the ID used to reference the property's globally 244 * unique identifier in the CLIENTPIDMAP property. 245 * @see VCardParameters#addPid(int, int) 246 */ 247 void addPid(int localId, int clientPidMapRef) { 248 parameters.addPid(localId, clientPidMapRef); 249 } 250 251 /** 252 * <p> 253 * Removes all PID values. 254 * </p> 255 * <p> 256 * <b>Supported versions:</b> {@code 4.0} 257 * </p> 258 * @see VCardParameters#removePids 259 */ 260 void removePids() { 261 parameters.removePids(); 262 } 263 264 /** 265 * <p> 266 * Gets the preference value. The lower the number, the more preferred this 267 * property instance is compared with other properties in the same vCard of 268 * the same type. If a property doesn't have a preference value, then it is 269 * considered the least preferred. 270 * </p> 271 * <p> 272 * <b>Supported versions:</b> {@code 4.0} 273 * </p> 274 * @return the preference value or null if it doesn't exist 275 * @see VCardParameters#getPref 276 */ 277 Integer getPref() { 278 return parameters.getPref(); 279 } 280 281 /** 282 * <p> 283 * Sets the preference value. The lower the number, the more preferred this 284 * property instance is compared with other properties in the same vCard of 285 * the same type. If a property doesn't have a preference value, then it is 286 * considered the least preferred. 287 * </p> 288 * <p> 289 * <b>Supported versions:</b> {@code 4.0} 290 * </p> 291 * @param pref the preference value or null to remove 292 * @see VCardParameters#setPref 293 */ 294 void setPref(Integer pref) { 295 parameters.setPref(pref); 296 } 297 298 /** 299 * Gets the language that the property value is written in. 300 * @return the language or null if not set 301 * @see VCardParameters#getLanguage 302 */ 303 String getLanguage() { 304 return parameters.getLanguage(); 305 } 306 307 /** 308 * Sets the language that the property value is written in. 309 * @param language the language or null to remove 310 * @see VCardParameters#setLanguage 311 */ 312 void setLanguage(String language) { 313 parameters.setLanguage(language); 314 } 315 316 /** 317 * Gets the sorted position of this property when it is grouped together 318 * with other properties of the same type. Properties with low index values 319 * are put at the beginning of the sorted list and properties with high 320 * index values are put at the end of the list. 321 * @return the index or null if not set 322 * @see VCardParameters#setIndex 323 */ 324 Integer getIndex() { 325 return parameters.getIndex(); 326 } 327 328 /** 329 * Sets the sorted position of this property when it is grouped together 330 * with other properties of the same type. Properties with low index values 331 * are put at the beginning of the sorted list and properties with high 332 * index values are put at the end of the list. 333 * @param index the index or null to remove 334 * @see VCardParameters#setIndex 335 */ 336 void setIndex(Integer index) { 337 parameters.setIndex(index); 338 } 339 }