001package ezvcard.parameter;
002
003import java.util.Objects;
004
005import ezvcard.property.ClientPidMap;
006
007/*
008 Copyright (c) 2012-2026, Michael Angstadt
009 All rights reserved.
010
011 Redistribution and use in source and binary forms, with or without
012 modification, are permitted provided that the following conditions are met: 
013
014 1. Redistributions of source code must retain the above copyright notice, this
015 list of conditions and the following disclaimer. 
016 2. Redistributions in binary form must reproduce the above copyright notice,
017 this list of conditions and the following disclaimer in the documentation
018 and/or other materials provided with the distribution. 
019
020 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
021 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
022 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
023 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
024 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
025 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
026 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
027 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
029 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030
031 The views and conclusions contained in the software and documentation are those
032 of the authors and should not be interpreted as representing official policies, 
033 either expressed or implied, of the FreeBSD Project.
034 */
035
036/**
037 * Represents a PID parameter value. A PID uniquely identifies a property. They
038 * are used when two different versions of the same vCard have to be merged
039 * together (called "synchronizing").
040 * @author Michael Angstadt
041 * @see <a href="http://tools.ietf.org/html/rfc6350#section-5.5">RFC 6350
042 * Section 5.5</a>
043 */
044public class Pid {
045        private final Integer localId;
046        private final Integer clientPidMapReference;
047
048        /**
049         * Creates a new PID.
050         * @param localId the local ID (cannot be null, must be positive)
051         * @param clientPidMapReference an integer that references the property's
052         * globally unique ID (optional, must be positive). It must match the first
053         * value in an existing {@link ClientPidMap} property
054         * @throws NullPointerException if local ID is null
055         */
056        public Pid(Integer localId, Integer clientPidMapReference) {
057                if (localId == null) {
058                        throw new NullPointerException("Local ID must not be null.");
059                }
060                this.localId = localId;
061                this.clientPidMapReference = clientPidMapReference;
062        }
063
064        /**
065         * Creates a new PID.
066         * @param localId the local ID (cannot be null, must be positive)
067         * @throws NullPointerException if local ID is null
068         */
069        public Pid(Integer localId) {
070                this(localId, null);
071        }
072
073        /**
074         * Gets the local ID
075         * @return the local ID
076         */
077        public Integer getLocalId() {
078                return localId;
079        }
080
081        /**
082         * Gets the reference to the property's globally unique ID (stored in a
083         * {@link ClientPidMap} property).
084         * @return the reference ID or null if not set
085         */
086        public Integer getClientPidMapReference() {
087                return clientPidMapReference;
088        }
089
090        /**
091         * Parses a string into a {@link Pid} object.
092         * @param value the string value (e.g. "1.2")
093         * @return the {@link Pid} object
094         * @throws NumberFormatException if there's a problem parsing the string
095         */
096        public static Pid valueOf(String value) {
097                int dot = value.indexOf('.');
098                String localIdStr;
099                String clientPidMapReferenceStr;
100                if (dot < 0) {
101                        localIdStr = value;
102                        clientPidMapReferenceStr = null;
103                } else {
104                        localIdStr = value.substring(0, dot);
105                        clientPidMapReferenceStr = (dot == value.length() - 1) ? null : value.substring(dot + 1);
106                }
107
108                Integer localId = Integer.valueOf(localIdStr);
109                Integer clientPidMapReference = (clientPidMapReferenceStr == null) ? null : Integer.valueOf(clientPidMapReferenceStr);
110                return new Pid(localId, clientPidMapReference);
111        }
112
113        @Override
114        public String toString() {
115                return (clientPidMapReference == null) ? Integer.toString(localId) : localId + "." + clientPidMapReference;
116        }
117
118        @Override
119        public int hashCode() {
120                return Objects.hash(clientPidMapReference, localId);
121        }
122
123        @Override
124        public boolean equals(Object obj) {
125                if (this == obj) return true;
126                if (obj == null) return false;
127                if (getClass() != obj.getClass()) return false;
128                Pid other = (Pid) obj;
129                return Objects.equals(clientPidMapReference, other.clientPidMapReference) && Objects.equals(localId, other.localId);
130        }
131}