google-nomulus/java/google/registry/model/registrar/RegistrarContact.java
shikhman f76bc70f91 Preserve test logs and test summary output for Kokoro CI runs
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=135494972
2016-10-14 16:57:43 -04:00

317 lines
9.6 KiB
Java

// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.registrar;
import static com.google.common.base.Functions.toStringFunction;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.difference;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
import static google.registry.util.ObjectifyUtils.OBJECTS_TO_KEYS;
import com.google.common.base.Enums;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.JsonMapBuilder;
import google.registry.model.Jsonifiable;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
* A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only
* enable key equality.
*
* <p>IMPORTANT NOTE: Any time that you change, update, or delete RegistrarContact entities, you
* *MUST* also modify the persisted Registrar entity with {@link Registrar#contactsRequireSyncing}
* set to true.
*/
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
@Entity
public class RegistrarContact extends ImmutableObject implements Jsonifiable {
@Parent
Key<Registrar> parent;
/**
* Registrar contacts types for partner communication tracking.
*
* <p><b>Note:</b> These types only matter to the registry. They are not meant to be used for
* WHOIS or RDAP results.
*/
public enum Type {
ABUSE("abuse", true),
ADMIN("primary", true),
BILLING("billing", true),
LEGAL("legal", true),
MARKETING("marketing", false),
TECH("technical", true),
WHOIS("whois-inquiry", true);
private final String displayName;
private final boolean required;
public String getDisplayName() {
return displayName;
}
public boolean isRequired() {
return required;
}
private Type(String display, boolean required) {
this.displayName = display;
this.required = required;
}
}
/** The name of the contact. */
String name;
/** The email address of the contact. */
@Id
String emailAddress;
/** The voice number of the contact. */
String phoneNumber;
/** The fax number of the contact. */
String faxNumber;
/**
* Multiple types are used to associate the registrar contact with
* various mailing groups. This data is internal to the registry.
*/
Set<Type> types;
/**
* A GAE user ID allowed to act as this registrar contact.
*
* <p>This can be derived from a known email address using http://email-to-gae-id.appspot.com.
*
* @see com.google.appengine.api.users.User#getUserId()
*/
@Index
String gaeUserId;
/**
* Whether this contact is publicly visible in WHOIS results as an Admin contact.
*/
boolean visibleInWhoisAsAdmin = false;
/**
* Whether this contact is publicly visible in WHOIS results as a Technical contact.
*/
boolean visibleInWhoisAsTech = false;
public static ImmutableSet<Type> typesFromCSV(String csv) {
return typesFromStrings(Arrays.asList(csv.split(",")));
}
public static ImmutableSet<Type> typesFromStrings(Iterable<String> typeNames) {
return FluentIterable.from(typeNames).transform(Enums.stringConverter(Type.class)).toSet();
}
/**
* Helper to update the contacts associated with a Registrar. This requires querying for the
* existing contacts, deleting existing contacts that are not part of the given {@code contacts}
* set, and then saving the given {@code contacts}.
*
* <p>IMPORTANT NOTE: If you call this method then it is your responsibility to also persist the
* relevant Registrar entity with the {@link Registrar#contactsRequireSyncing} field set to true.
*/
public static void updateContacts(
final Registrar registrar, final Set<RegistrarContact> contacts) {
ofy().transact(new VoidWork() {
@Override
public void vrun() {
ofy().delete().keys(difference(
ImmutableSet.copyOf(
ofy().load().type(RegistrarContact.class).ancestor(registrar).keys()),
FluentIterable.from(contacts).transform(OBJECTS_TO_KEYS).toSet()));
ofy().save().entities(contacts);
}});
}
public Key<Registrar> getParent() {
return parent;
}
public String getName() {
return name;
}
public String getEmailAddress() {
return emailAddress;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getFaxNumber() {
return faxNumber;
}
public ImmutableSortedSet<Type> getTypes() {
return nullToEmptyImmutableSortedCopy(types);
}
public boolean getVisibleInWhoisAsAdmin() {
return visibleInWhoisAsAdmin;
}
public boolean getVisibleInWhoisAsTech() {
return visibleInWhoisAsTech;
}
public String getGaeUserId() {
return gaeUserId;
}
public Builder asBuilder() {
return new Builder(clone(this));
}
/**
* Returns a string representation that's human friendly.
*
* <p>The output will look something like this:<pre> {@code
*
* Some Person
* person@example.com
* Tel: +1.2125650666
* Types: [ADMIN, WHOIS]
* Visible in WHOIS as Admin contact: Yes
* Visible in WHOIS as Technical contact: No
* GAE-UserID: 1234567890}</pre>
*/
public String toStringMultilinePlainText() {
StringBuilder result = new StringBuilder(256);
result.append(getName()).append('\n');
result.append(getEmailAddress()).append('\n');
if (phoneNumber != null) {
result.append("Tel: ").append(getPhoneNumber()).append('\n');
}
if (faxNumber != null) {
result.append("Fax: ").append(getFaxNumber()).append('\n');
}
result.append("Types: ").append(getTypes()).append('\n');
result.append("Visible in WHOIS as Admin contact: ")
.append(getVisibleInWhoisAsAdmin() ? "Yes" : "No")
.append("\n");
result.append("Visible in WHOIS as Technical contact: ")
.append(getVisibleInWhoisAsTech() ? "Yes" : "No")
.append("\n");
if (getGaeUserId() != null) {
result.append("GAE-UserID: ").append(getGaeUserId()).append('\n');
}
return result.toString();
}
@Override
public Map<String, Object> toJsonMap() {
return new JsonMapBuilder()
.put("name", name)
.put("emailAddress", emailAddress)
.put("phoneNumber", phoneNumber)
.put("faxNumber", faxNumber)
.put("types", Joiner.on(',').join(transform(getTypes(), toStringFunction())))
.put("visibleInWhoisAsAdmin", visibleInWhoisAsAdmin)
.put("visibleInWhoisAsTech", visibleInWhoisAsTech)
.put("gaeUserId", gaeUserId)
.build();
}
/** A builder for constructing a {@link RegistrarContact}, since it is immutable. */
public static class Builder extends Buildable.Builder<RegistrarContact> {
public Builder() {}
private Builder(RegistrarContact instance) {
super(instance);
}
public Builder setParent(Registrar parent) {
return this.setParent(Key.create(parent));
}
public Builder setParent(Key<Registrar> parentKey) {
getInstance().parent = parentKey;
return this;
}
/** Build the registrar, nullifying empty fields. */
@Override
public RegistrarContact build() {
checkNotNull(getInstance().parent, "Registrar parent cannot be null");
checkNotNull(getInstance().emailAddress, "Email address cannot be null");
return cloneEmptyToNull(super.build());
}
public Builder setName(String name) {
getInstance().name = name;
return this;
}
public Builder setEmailAddress(String emailAddress) {
getInstance().emailAddress = emailAddress;
return this;
}
public Builder setPhoneNumber(String phoneNumber) {
getInstance().phoneNumber = phoneNumber;
return this;
}
public Builder setFaxNumber(String faxNumber) {
getInstance().faxNumber = faxNumber;
return this;
}
public Builder setTypes(Iterable<Type> types) {
getInstance().types = ImmutableSet.copyOf(types);
return this;
}
public Builder setVisibleInWhoisAsAdmin(boolean visible) {
getInstance().visibleInWhoisAsAdmin = visible;
return this;
}
public Builder setVisibleInWhoisAsTech(boolean visible) {
getInstance().visibleInWhoisAsTech = visible;
return this;
}
public Builder setGaeUserId(String gaeUserId) {
getInstance().gaeUserId = gaeUserId;
return this;
}
}
}