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}