001package ezvcard.property; 002 003import java.util.LinkedHashMap; 004import java.util.List; 005import java.util.Map; 006import java.util.UUID; 007 008import ezvcard.SupportedVersions; 009import ezvcard.VCard; 010import ezvcard.VCardVersion; 011import ezvcard.ValidationWarning; 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 * <p> 044 * Maps a globally-unique URI to a PID parameter value. The PID parameter can be 045 * set on any property where multiple instances are allowed (such as 046 * {@link Email} or {@link Address}, but not {@link StructuredName} because only 047 * 1 instance of it is allowed). It allows an individual property instance to be 048 * uniquely identifiable. 049 * </p> 050 * 051 * <p> 052 * This property, along with the PID parameter, is used during the 053 * synchronization (merging) process of two versions of the same vCard. For 054 * example, if the user has a copy of her vCard on her desktop computer and her 055 * smart phone, and she makes different modifications to each copy, then the two 056 * copies could be synchronized in order to merge all the changes into a single, 057 * new vCard. 058 * </p> 059 * 060 * <p> 061 * <b>Code sample</b> 062 * </p> 063 * 064 * <pre class="brush:java"> 065 * VCard vcard = new VCard(); 066 * 067 * Address adr = new Address(); 068 * adr.addPid(1, 1); 069 * vcard.addAddress(adr); 070 * 071 * Email email = vcard.addEmail("johndoe@hotmail.com"); 072 * emai.addPid(1, 1); 073 * email = vcard.addEmail("jdoe@company.com"); 074 * email.addPid(2, 2); 075 * 076 * //specify the URI to use 077 * ClientPidMap clientpidmap = new ClientPidMap(1, "urn:uuid:03a0e51f-d1aa-4385-8a53-e29025acd8af"); 078 * vcard.addClientPidMap(clientpidmap); 079 * 080 * //or, generate a random URI 081 * clientpidmap = ClientPidMap.random(2); 082 * vcard.addClientPidMap(clientpidmap); 083 * </pre> 084 * 085 * <p> 086 * <b>Property name:</b> {@code CLIENTPIDMAP} 087 * </p> 088 * <p> 089 * <b>Supported versions:</b> {@code 4.0} 090 * </p> 091 * @author Michael Angstadt 092 * @see <a href="http://tools.ietf.org/html/rfc6350#page-47">RFC 6350 p.47</a> 093 */ 094@SupportedVersions(VCardVersion.V4_0) 095public class ClientPidMap extends VCardProperty { 096 private Integer pid; 097 private String uri; 098 099 /** 100 * Creates a client PID map property. 101 * @param pid the PID 102 * @param uri the globally unique URI 103 */ 104 public ClientPidMap(Integer pid, String uri) { 105 this.pid = pid; 106 this.uri = uri; 107 } 108 109 /** 110 * Copy constructor. 111 * @param original the property to make a copy of 112 */ 113 public ClientPidMap(ClientPidMap original) { 114 super(original); 115 pid = original.pid; 116 uri = original.uri; 117 } 118 119 /** 120 * Generates a CLIENTPIDMAP type that contains a random UID URI. 121 * @param pid the PID 122 * @return a CLIENTPIDMAP type with a random UID URI 123 */ 124 public static ClientPidMap random(Integer pid) { 125 String uuid = UUID.randomUUID().toString(); 126 return new ClientPidMap(pid, "urn:uuid:" + uuid); 127 } 128 129 /** 130 * Gets the value that is used to link the URI in this property to the 131 * property that the URI belongs to. 132 * @return the PID 133 */ 134 public Integer getPid() { 135 return pid; 136 } 137 138 /** 139 * Gets the value that is used to link the URI in this property to the 140 * property that the URI belongs to. 141 * @param pid the PID 142 */ 143 public void setPid(Integer pid) { 144 this.pid = pid; 145 } 146 147 /** 148 * Gets the URI. 149 * @return the URI 150 */ 151 public String getUri() { 152 return uri; 153 } 154 155 /** 156 * Sets the URI. 157 * @param uri the URI 158 */ 159 public void setUri(String uri) { 160 this.uri = uri; 161 } 162 163 @Override 164 protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) { 165 if (pid == null && uri == null) { 166 warnings.add(new ValidationWarning(8)); 167 } 168 } 169 170 @Override 171 protected Map<String, Object> toStringValues() { 172 Map<String, Object> values = new LinkedHashMap<>(); 173 values.put("pid", pid); 174 values.put("uri", uri); 175 return values; 176 } 177 178 @Override 179 public ClientPidMap copy() { 180 return new ClientPidMap(this); 181 } 182 183 @Override 184 public int hashCode() { 185 final int prime = 31; 186 int result = super.hashCode(); 187 result = prime * result + ((pid == null) ? 0 : pid.hashCode()); 188 result = prime * result + ((uri == null) ? 0 : uri.hashCode()); 189 return result; 190 } 191 192 @Override 193 public boolean equals(Object obj) { 194 if (this == obj) return true; 195 if (!super.equals(obj)) return false; 196 ClientPidMap other = (ClientPidMap) obj; 197 if (pid == null) { 198 if (other.pid != null) return false; 199 } else if (!pid.equals(other.pid)) return false; 200 if (uri == null) { 201 if (other.uri != null) return false; 202 } else if (!uri.equals(other.uri)) return false; 203 return true; 204 } 205}