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}