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}