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