001// SPDX-FileCopyrightText: 2020 Paul Schaub <vanitasvitae@fsfe.org>, 2021 Flowcrypt a.s. 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.key.util; 006 007import javax.annotation.Nonnull; 008 009public final class UserId implements CharSequence { 010 public static final class Builder { 011 private String name; 012 private String comment; 013 private String email; 014 015 private Builder() { 016 } 017 018 private Builder(String name, String comment, String email) { 019 this.name = name; 020 this.comment = comment; 021 this.email = email; 022 } 023 024 public Builder withName(String name) { 025 checkNotNull("name", name); 026 this.name = name; 027 return this; 028 } 029 030 public Builder withComment(String comment) { 031 checkNotNull("comment", comment); 032 this.comment = comment; 033 return this; 034 } 035 036 public Builder withEmail(String email) { 037 checkNotNull("email", email); 038 this.email = email; 039 return this; 040 } 041 042 public Builder noName() { 043 name = null; 044 return this; 045 } 046 047 public Builder noComment() { 048 comment = null; 049 return this; 050 } 051 052 public Builder noEmail() { 053 email = null; 054 return this; 055 } 056 057 public UserId build() { 058 return new UserId(name, comment, email); 059 } 060 } 061 062 private final String name; 063 private final String comment; 064 private final String email; 065 private long hash = Long.MAX_VALUE; 066 067 private UserId(String name, String comment, String email) { 068 this.name = name; 069 this.comment = comment; 070 this.email = email; 071 } 072 073 public static UserId onlyEmail(String email) { 074 checkNotNull("email", email); 075 return new UserId(null, null, email); 076 } 077 078 public static UserId nameAndEmail(String name, String email) { 079 checkNotNull("name", name); 080 checkNotNull("email", email); 081 return new UserId(name, null, email); 082 } 083 084 public static Builder newBuilder() { 085 return new Builder(); 086 } 087 088 public Builder toBuilder() { 089 return new Builder(name, comment, email); 090 } 091 092 public String getName() { 093 return name; 094 } 095 096 public String getComment() { 097 return comment; 098 } 099 100 public String getEmail() { 101 return email; 102 } 103 104 @Override 105 public int length() { 106 return toString().length(); 107 } 108 109 @Override 110 public char charAt(int i) { 111 return toString().charAt(i); 112 } 113 114 @Override 115 public @Nonnull CharSequence subSequence(int i, int i1) { 116 return toString().subSequence(i, i1); 117 } 118 119 @Override 120 public @Nonnull String toString() { 121 return asString(false); 122 } 123 124 /** 125 * Returns a string representation of the object. 126 * @param ignoreEmptyValues Flag which indicates that empty string values should not be outputted. 127 * @return a string representation of the object. 128 */ 129 public String asString(boolean ignoreEmptyValues) { 130 StringBuilder sb = new StringBuilder(); 131 if (name != null && (!ignoreEmptyValues || !name.isEmpty())) { 132 sb.append(name); 133 } 134 if (comment != null && (!ignoreEmptyValues || !comment.isEmpty())) { 135 sb.append(" (").append(comment).append(')'); 136 } 137 if (email != null && (!ignoreEmptyValues || !email.isEmpty())) { 138 final boolean moreThanJustEmail = sb.length() > 0; 139 if (moreThanJustEmail) sb.append(" <"); 140 sb.append(email); 141 if (moreThanJustEmail) sb.append('>'); 142 } 143 return sb.toString(); 144 } 145 146 @Override 147 public boolean equals(Object o) { 148 if (o == null) return false; 149 if (o == this) return true; 150 if (!(o instanceof UserId)) return false; 151 final UserId other = (UserId) o; 152 return isEqualComponent(name, other.name, false) 153 && isEqualComponent(comment, other.comment, false) 154 && isEqualComponent(email, other.email, true); 155 } 156 157 @Override 158 public int hashCode() { 159 if (hash != Long.MAX_VALUE) { 160 return (int) hash; 161 } else { 162 int hashCode = 7; 163 hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode()); 164 hashCode = 31 * hashCode + (comment == null ? 0 : comment.hashCode()); 165 hashCode = 31 * hashCode + (email == null ? 0 : email.toLowerCase().hashCode()); 166 this.hash = hashCode; 167 return hashCode; 168 } 169 } 170 171 private static boolean isEqualComponent(String value, String otherValue, boolean ignoreCase) { 172 final boolean valueIsNull = (value == null); 173 final boolean otherValueIsNull = (otherValue == null); 174 return (valueIsNull && otherValueIsNull) 175 || (!valueIsNull && !otherValueIsNull 176 && (ignoreCase ? value.equalsIgnoreCase(otherValue) : value.equals(otherValue))); 177 } 178 179 private static void checkNotNull(String paramName, String value) { 180 if (value == null) { 181 throw new IllegalArgumentException(paramName + " must be not null"); 182 } 183 } 184}