// SPDX-FileCopyrightText: 2020 Paul Schaub , 2021 Flowcrypt a.s. // // SPDX-License-Identifier: Apache-2.0 package org.pgpainless.key.util; import javax.annotation.Nonnull; public final class UserId implements CharSequence { public static final class Builder { private String name; private String comment; private String email; private Builder() { } private Builder(String name, String comment, String email) { this.name = name; this.comment = comment; this.email = email; } public Builder withName(String name) { checkNotNull("name", name); this.name = name; return this; } public Builder withComment(String comment) { checkNotNull("comment", comment); this.comment = comment; return this; } public Builder withEmail(String email) { checkNotNull("email", email); this.email = email; return this; } public Builder noName() { name = null; return this; } public Builder noComment() { comment = null; return this; } public Builder noEmail() { email = null; return this; } public UserId build() { return new UserId(name, comment, email); } } private final String name; private final String comment; private final String email; private long hash = Long.MAX_VALUE; private UserId(String name, String comment, String email) { this.name = name; this.comment = comment; this.email = email; } public static UserId onlyEmail(String email) { checkNotNull("email", email); return new UserId(null, null, email); } public static UserId nameAndEmail(String name, String email) { checkNotNull("name", name); checkNotNull("email", email); return new UserId(name, null, email); } public static Builder newBuilder() { return new Builder(); } public Builder toBuilder() { return new Builder(name, comment, email); } public String getName() { return name; } public String getComment() { return comment; } public String getEmail() { return email; } @Override public int length() { return toString().length(); } @Override public char charAt(int i) { return toString().charAt(i); } @Override public @Nonnull CharSequence subSequence(int i, int i1) { return toString().subSequence(i, i1); } @Override public @Nonnull String toString() { return asString(false); } /** * Returns a string representation of the object. * @param ignoreEmptyValues Flag which indicates that empty string values should not be outputted. * @return a string representation of the object. */ public String asString(boolean ignoreEmptyValues) { StringBuilder sb = new StringBuilder(); if (name != null && (!ignoreEmptyValues || !name.isEmpty())) { sb.append(name); } if (comment != null && (!ignoreEmptyValues || !comment.isEmpty())) { sb.append(" (").append(comment).append(')'); } if (email != null && (!ignoreEmptyValues || !email.isEmpty())) { final boolean moreThanJustEmail = sb.length() > 0; if (moreThanJustEmail) sb.append(" <"); sb.append(email); if (moreThanJustEmail) sb.append('>'); } return sb.toString(); } @Override public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (!(o instanceof UserId)) return false; final UserId other = (UserId) o; return isEqualComponent(name, other.name, false) && isEqualComponent(comment, other.comment, false) && isEqualComponent(email, other.email, true); } @Override public int hashCode() { if (hash != Long.MAX_VALUE) { return (int) hash; } else { int hashCode = 7; hashCode = 31 * hashCode + (name == null ? 0 : name.hashCode()); hashCode = 31 * hashCode + (comment == null ? 0 : comment.hashCode()); hashCode = 31 * hashCode + (email == null ? 0 : email.toLowerCase().hashCode()); this.hash = hashCode; return hashCode; } } private static boolean isEqualComponent(String value, String otherValue, boolean ignoreCase) { final boolean valueIsNull = (value == null); final boolean otherValueIsNull = (otherValue == null); return (valueIsNull && otherValueIsNull) || (!valueIsNull && !otherValueIsNull && (ignoreCase ? value.equalsIgnoreCase(otherValue) : value.equals(otherValue))); } private static void checkNotNull(String paramName, String value) { if (value == null) { throw new IllegalArgumentException(paramName + " must be not null"); } } }