mv com/google/domain/registry google/registry

This change renames directories in preparation for the great package
rename. The repository is now in a broken state because the code
itself hasn't been updated. However this should ensure that git
correctly preserves history for each file.
This commit is contained in:
Justine Tunney 2016-05-13 18:55:08 -04:00
parent a41677aea1
commit 5012893c1d
2396 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,37 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import com.google.domain.registry.model.eppcommon.Address;
import com.googlecode.objectify.annotation.Embed;
/**
* EPP Contact Address
* <p>
* This class is embedded inside the {@link PostalInfo} of an EPP contact to hold its address. The
* fields are all defined in parent class {@link Address}, but the subclass is still necessary to
* pick up the contact namespace.
* <p>
* This does not implement {@code Overlayable} because it is intended to be bulk replaced on update.
*
* @see PostalInfo
*/
@Embed
public class ContactAddress extends Address {
/** Builder for {@link ContactAddress}. */
public static class Builder extends Address.Builder<ContactAddress> {}
}

View file

@ -0,0 +1,51 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.eppcommon.AuthInfo;
import com.googlecode.objectify.annotation.Embed;
import javax.xml.bind.annotation.XmlType;
/** A version of authInfo specifically for contacts. */
@Embed
@XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0")
public class ContactAuthInfo extends AuthInfo {
public static ContactAuthInfo create(PasswordAuth pw) {
ContactAuthInfo instance = new ContactAuthInfo();
instance.pw = pw;
return instance;
}
@Override
public void verifyAuthorizedFor(EppResource eppResource) throws BadAuthInfoException {
ContactResource contact = (ContactResource) eppResource;
PasswordAuth passwordAuth = checkNotNull(getPw());
// It's rather strange to specify a repoId on a contact auth info. Instead of explicitly
// rejecting it, we'll just make sure the repoId matches this particular contact.
if (passwordAuth.getRepoId() != null && !contact.getRepoId().equals(getRepoId())) {
throw new BadAuthInfoException();
}
if (!contact.getAuthInfo().getPw().getValue().equals(passwordAuth.getValue())) {
throw new BadAuthInfoException();
}
}
}

View file

@ -0,0 +1,239 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import static com.google.common.base.Preconditions.checkState;
import static com.google.domain.registry.util.CollectionUtils.nullToEmpty;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.contact.ContactResource.Builder;
import com.google.domain.registry.model.contact.PostalInfo.Type;
import com.google.domain.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCheck;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
import com.google.domain.registry.model.eppinput.ResourceCommand.ResourceUpdate;
import com.google.domain.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/** A collection of {@link ContactResource} commands. */
public class ContactCommand {
/** The fields on "chgType" from {@link "http://tools.ietf.org/html/rfc5733"}. */
@XmlTransient
public static class ContactCreateOrChange extends ImmutableObject
implements ResourceCreateOrChange<ContactResource.Builder> {
/** Postal info for the contact. */
List<PostalInfo> postalInfo;
/** Contacts voice number. */
ContactPhoneNumber voice;
/** Contacts fax number. */
ContactPhoneNumber fax;
/** Contacts email address. */
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
String email;
/** Authorization info (aka transfer secret) of the contact. */
ContactAuthInfo authInfo;
/** Disclosure policy. */
Disclose disclose;
/** Helper method to move between the postal infos list and the individual getters. */
protected Map<Type, PostalInfo> getPostalInfosAsMap() {
// There can be no more than 2 postalInfos (enforced by the schema), and if there are 2 they
// must be of different types (not enforced). If the type is repeated, uniqueIndex will throw.
checkState(nullToEmpty(postalInfo).size() <= 2);
return Maps.uniqueIndex(nullToEmpty(postalInfo), new Function<PostalInfo, Type>() {
@Override
public Type apply(PostalInfo info) {
return info.getType();
}});
}
@Override
public void applyTo(Builder builder) {
if (authInfo != null) {
builder.setAuthInfo(authInfo);
}
if (disclose != null) {
builder.setDisclose(disclose);
}
if (email != null) {
builder.setEmailAddress(email);
}
if (fax != null) {
builder.setFaxNumber(fax);
}
if (voice != null) {
builder.setVoiceNumber(voice);
}
}
}
/** An abstract contact command that contains authorization info. */
@XmlTransient
public static class AbstractContactAuthCommand extends AbstractSingleResourceCommand {
/** Authorization info used to validate if client has permissions to perform this operation. */
ContactAuthInfo authInfo;
@Override
public ContactAuthInfo getAuthInfo() {
return authInfo;
}
}
/**
* A create command for a {@link ContactResource}, mapping "createType" from
* {@link "http://tools.ietf.org/html/rfc5733"}.
*/
@XmlType(propOrder = {"contactId", "postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
@XmlRootElement
public static class Create extends ContactCreateOrChange
implements SingleResourceCommand, ResourceCreateOrChange<ContactResource.Builder> {
/**
* Unique identifier for this contact.
* <p>
* This is only unique in the sense that for any given lifetime specified as the time range from
* (creationTime, deletionTime) there can only be one contact in the datastore with this id.
* However, there can be many contacts with the same id and non-overlapping lifetimes.
*/
@XmlElement(name = "id")
String contactId;
@Override
public String getTargetId() {
return contactId;
}
@Override
public ContactAuthInfo getAuthInfo() {
return authInfo;
}
@Override
public void applyTo(ContactResource.Builder builder) {
super.applyTo(builder);
if (contactId != null) {
builder.setContactId(contactId);
}
Map<Type, PostalInfo> postalInfosAsMap = getPostalInfosAsMap();
if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) {
builder.setInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED));
}
if (postalInfosAsMap.containsKey(Type.LOCALIZED)) {
builder.setLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED));
}
}
}
/** A delete command for a {@link ContactResource}. */
@XmlRootElement
public static class Delete extends AbstractSingleResourceCommand {}
/** An info request for a {@link ContactResource}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "authInfo"})
public static class Info extends AbstractContactAuthCommand {}
/** A check request for {@link ContactResource}. */
@XmlRootElement
public static class Check extends ResourceCheck {}
/** A transfer operation for a {@link ContactResource}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "authInfo"})
public static class Transfer extends AbstractContactAuthCommand {}
/** An update to a {@link ContactResource}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update
extends ResourceUpdate<Update.AddRemove, ContactResource.Builder, Update.Change> {
@XmlElement(name = "chg")
protected Change innerChange;
@XmlElement(name = "add")
protected AddRemove innerAdd;
@XmlElement(name = "rem")
protected AddRemove innerRemove;
@Override
protected Change getNullableInnerChange() {
return innerChange;
}
@Override
protected AddRemove getNullableInnerAdd() {
return innerAdd;
}
@Override
protected AddRemove getNullableInnerRemove() {
return innerRemove;
}
/** The inner change type on a contact update command. */
public static class AddRemove extends ResourceUpdate.AddRemove {}
/** The inner change type on a contact update command. */
@XmlType(propOrder = {"postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
public static class Change extends ContactCreateOrChange {
/**
* The spec requires the following behaviors:
* <ul>
* <li>If you update part of a postal info, the fields that you didn't update are unchanged.
* <li>If you update one postal info but not the other, the other is deleted.
* </ul>
* Therefore, if you want to preserve one postal info and update another you need to send the
* update and also something that technically updates the preserved one, even if it only
* "updates" it by setting just one field to the same value.
*/
@Override
public void applyTo(ContactResource.Builder builder) {
super.applyTo(builder);
Map<Type, PostalInfo> postalInfosAsMap = getPostalInfosAsMap();
if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) {
builder.overlayInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED));
if (postalInfosAsMap.size() == 1) {
builder.setLocalizedPostalInfo(null);
}
}
if (postalInfosAsMap.containsKey(Type.LOCALIZED)) {
builder.overlayLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED));
if (postalInfosAsMap.size() == 1) {
builder.setInternationalizedPostalInfo(null);
}
}
}
}
}
}

View file

@ -0,0 +1,35 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import com.google.domain.registry.model.eppcommon.PhoneNumber;
import com.googlecode.objectify.annotation.Embed;
/**
* EPP Contact Phone Number
* <p>
* This class is embedded inside a {@link ContactResource} hold the phone number of an EPP contact.
* The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is still
* necessary to pick up the contact namespace.
*
* @see ContactResource
*/
@Embed
public class ContactPhoneNumber extends PhoneNumber {
/** Builder for {@link ContactPhoneNumber}. */
public static class Builder extends PhoneNumber.Builder<ContactPhoneNumber> {}
}

View file

@ -0,0 +1,260 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.domain.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime;
import static com.google.domain.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.domain.registry.model.EppResource;
import com.google.domain.registry.model.EppResource.ForeignKeyedEppResource;
import com.google.domain.registry.model.annotations.ExternalMessagingName;
import com.google.domain.registry.model.contact.PostalInfo.Type;
import com.google.domain.registry.model.eppcommon.AuthInfo;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.condition.IfNull;
import org.joda.time.DateTime;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/** A persistable Contact resource including mutable and non-mutable fields. */
@XmlRootElement(name = "infData")
@XmlType(propOrder = {
"contactId",
"repoId",
"status",
"postalInfosAsList",
"voice",
"fax",
"email",
"currentSponsorClientId",
"creationClientId",
"creationTime",
"lastEppUpdateClientId",
"lastEppUpdateTime",
"lastTransferTime",
"authInfo",
"disclose" })
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
@Entity
@ExternalMessagingName("contact")
public class ContactResource extends EppResource implements ForeignKeyedEppResource {
/**
* Unique identifier for this contact.
* <p>
* This is only unique in the sense that for any given lifetime specified as the time range from
* (creationTime, deletionTime) there can only be one contact in the datastore with this id.
* However, there can be many contacts with the same id and non-overlapping lifetimes.
*/
@XmlTransient
String contactId;
/**
* Localized postal info for the contact. All contained values must be representable in the 7-bit
* US-ASCII character set. Personal info; cleared by wipeOut().
*/
@IgnoreSave(IfNull.class)
@XmlTransient
PostalInfo localizedPostalInfo;
/** Internationalized postal info for the contact. Personal info; cleared by wipeOut(). */
@IgnoreSave(IfNull.class)
@XmlTransient
PostalInfo internationalizedPostalInfo;
/** Contacts voice number. Personal info; cleared by wipeOut(). */
@IgnoreSave(IfNull.class)
ContactPhoneNumber voice;
/** Contacts fax number. Personal info; cleared by wipeOut(). */
@IgnoreSave(IfNull.class)
ContactPhoneNumber fax;
/** Contacts email address. Personal info; cleared by wipeOut(). */
@IgnoreSave(IfNull.class)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
String email;
/** Authorization info (aka transfer secret) of the contact. */
ContactAuthInfo authInfo;
// If any new fields are added which contain personal information, make sure they are cleared by
// the wipeOut() function, so that data is not kept around for deleted contacts.
/** Disclosure policy. */
@IgnoreSave(IfNull.class)
Disclose disclose;
@XmlElement(name = "id")
public String getContactId() {
return contactId;
}
public PostalInfo getLocalizedPostalInfo() {
return localizedPostalInfo;
}
public PostalInfo getInternationalizedPostalInfo() {
return internationalizedPostalInfo;
}
public ContactPhoneNumber getVoiceNumber() {
return voice;
}
public ContactPhoneNumber getFaxNumber() {
return fax;
}
public String getEmailAddress() {
return email;
}
public AuthInfo getAuthInfo() {
return authInfo;
}
public Disclose getDisclose() {
return disclose;
}
@Override
public String getForeignKey() {
return contactId;
}
/**
* Postal info for the contact.
* <p>
* The XML marshalling expects the {@link PostalInfo} objects in a list, but we can't actually
* persist them to datastore that way because Objectify can't handle collections of embedded
* objects that themselves contain collections, and there's a list of streets inside. This method
* transforms the persisted format to the XML format for marshalling.
*/
@XmlElement(name = "postalInfo")
public List<PostalInfo> getPostalInfosAsList() {
return FluentIterable
.from(Lists.newArrayList(localizedPostalInfo, internationalizedPostalInfo))
.filter(Predicates.notNull())
.toList();
}
@Override
public ContactResource cloneProjectedAtTime(DateTime now) {
Builder builder = this.asBuilder();
projectResourceOntoBuilderAtTime(this, builder, now);
return builder.build();
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link ContactResource}, since it is immutable. */
public static class Builder extends EppResource.Builder<ContactResource, Builder> {
public Builder() {}
private Builder(ContactResource instance) {
super(instance);
}
public Builder setContactId(String contactId) {
getInstance().contactId = contactId;
return this;
}
public Builder setLocalizedPostalInfo(PostalInfo localizedPostalInfo) {
checkArgument(localizedPostalInfo == null
|| Type.LOCALIZED.equals(localizedPostalInfo.getType()));
getInstance().localizedPostalInfo = localizedPostalInfo;
return this;
}
public Builder setInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) {
checkArgument(internationalizedPostalInfo == null
|| Type.INTERNATIONALIZED.equals(internationalizedPostalInfo.getType()));
getInstance().internationalizedPostalInfo = internationalizedPostalInfo;
return this;
}
public Builder overlayLocalizedPostalInfo(PostalInfo localizedPostalInfo) {
return setLocalizedPostalInfo(getInstance().localizedPostalInfo == null
? localizedPostalInfo
: getInstance().localizedPostalInfo.overlay(localizedPostalInfo));
}
public Builder overlayInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) {
return setInternationalizedPostalInfo(getInstance().internationalizedPostalInfo == null
? internationalizedPostalInfo
: getInstance().internationalizedPostalInfo.overlay(internationalizedPostalInfo));
}
public Builder setVoiceNumber(ContactPhoneNumber voiceNumber) {
getInstance().voice = voiceNumber;
return this;
}
public Builder setFaxNumber(ContactPhoneNumber faxNumber) {
getInstance().fax = faxNumber;
return this;
}
public Builder setEmailAddress(String emailAddress) {
getInstance().email = emailAddress;
return this;
}
public Builder setAuthInfo(ContactAuthInfo authInfo) {
getInstance().authInfo = authInfo;
return this;
}
public Builder setDisclose(Disclose disclose) {
getInstance().disclose = disclose;
return this;
}
@Override
public Builder wipeOut() {
this.setEmailAddress(null);
this.setFaxNumber(null);
this.setInternationalizedPostalInfo(null);
this.setLocalizedPostalInfo(null);
this.setVoiceNumber(null);
return super.wipeOut();
}
@Override
public ContactResource build() {
return super.build();
}
}
}

View file

@ -0,0 +1,136 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import static com.google.domain.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.domain.registry.model.Buildable;
import com.google.domain.registry.model.ImmutableObject;
import com.google.domain.registry.model.eppcommon.PresenceMarker;
import com.googlecode.objectify.annotation.Embed;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
/** The "discloseType" from {@link "http://tools.ietf.org/html/rfc5733"}. */
@Embed
@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"})
public class Disclose extends ImmutableObject {
List<PostalInfoChoice> name;
List<PostalInfoChoice> org;
List<PostalInfoChoice> addr;
PresenceMarker voice;
PresenceMarker fax;
PresenceMarker email;
@XmlAttribute
Boolean flag;
public ImmutableList<PostalInfoChoice> getNames() {
return nullToEmptyImmutableCopy(name);
}
public ImmutableList<PostalInfoChoice> getOrgs() {
return nullToEmptyImmutableCopy(org);
}
public ImmutableList<PostalInfoChoice> getAddrs() {
return nullToEmptyImmutableCopy(addr);
}
public PresenceMarker getVoice() {
return voice;
}
public PresenceMarker getFax() {
return fax;
}
public PresenceMarker getEmail() {
return email;
}
public Boolean getFlag() {
return flag;
}
/** The "intLocType" from {@link "http://tools.ietf.org/html/rfc5733"}. */
@Embed
public static class PostalInfoChoice extends ImmutableObject {
@XmlAttribute
PostalInfo.Type type;
public PostalInfo.Type getType() {
return type;
}
@VisibleForTesting
public static PostalInfoChoice create(PostalInfo.Type type) {
PostalInfoChoice instance = new PostalInfoChoice();
instance.type = type;
return instance;
}
}
/** A builder for {@link Disclose} since it is immutable. */
@VisibleForTesting
public static class Builder extends Buildable.Builder<Disclose> {
public Builder setNames(ImmutableList<PostalInfoChoice> names) {
getInstance().name = names;
return this;
}
public Builder setOrgs(ImmutableList<PostalInfoChoice> orgs) {
getInstance().org = orgs;
return this;
}
public Builder setAddrs(ImmutableList<PostalInfoChoice> addrs) {
getInstance().addr = addrs;
return this;
}
public Builder setVoice(PresenceMarker voice) {
getInstance().voice = voice;
return this;
}
public Builder setFax(PresenceMarker fax) {
getInstance().fax = fax;
return this;
}
public Builder setEmail(PresenceMarker email) {
getInstance().email = email;
return this;
}
public Builder setFlag(boolean flag) {
getInstance().flag = flag;
return this;
}
}
}

View file

@ -0,0 +1,122 @@
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model.contact;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Optional;
import com.google.domain.registry.model.Buildable;
import com.google.domain.registry.model.Buildable.Overlayable;
import com.google.domain.registry.model.ImmutableObject;
import com.googlecode.objectify.annotation.Embed;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Implementation of both "postalInfoType" and "chgPostalInfoType" from
* {@link "http://tools.ietf.org/html/rfc5733"}.
*/
@Embed
@XmlType(propOrder = {"name", "org", "address", "type"})
public class PostalInfo extends ImmutableObject implements Overlayable<PostalInfo> {
/** The type of the address, either localized or international. */
public enum Type {
@XmlEnumValue("loc")
LOCALIZED,
@XmlEnumValue("int")
INTERNATIONALIZED
}
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
String name;
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
String org;
@XmlElement(name = "addr")
ContactAddress address;
@XmlAttribute
Type type;
public String getName() {
return name;
}
public String getOrg() {
return org;
}
public ContactAddress getAddress() {
return address;
}
public Type getType() {
return type;
}
@Override
public PostalInfo overlay(PostalInfo source) {
// Don't overlay the type field, as that should never change.
checkState(source.type == null || source.type == type);
return asBuilder()
.setName(Optional.fromNullable(source.getName()).or(Optional.fromNullable(name)).orNull())
.setOrg(Optional.fromNullable(source.getOrg()).or(Optional.fromNullable(org)).orNull())
.setAddress(
Optional.fromNullable(source.getAddress()).or(Optional.fromNullable(address)).orNull())
.build();
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link PostalInfo}, since its changes get overlayed. */
public static class Builder extends Buildable.Builder<PostalInfo> {
public Builder() {}
private Builder(PostalInfo instance) {
super(instance);
}
public Builder setName(String name) {
getInstance().name = name;
return this;
}
public Builder setOrg(String org) {
getInstance().org = org;
return this;
}
public Builder setAddress(ContactAddress address) {
getInstance().address = address;
return this;
}
public Builder setType(Type type) {
getInstance().type = type;
return this;
}
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry 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.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:contact-1.0",
xmlns = @XmlNs(prefix = "contact", namespaceURI = "urn:ietf:params:xml:ns:contact-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
package com.google.domain.registry.model.contact;
import com.google.domain.registry.xml.UtcDateTimeAdapter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;