diff --git a/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml b/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml index f54000d2d..45656832d 100644 --- a/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml +++ b/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml @@ -10,7 +10,7 @@ - + @@ -26,28 +26,44 @@ - + + + + + + + + + + + - + + + + + + + - + diff --git a/java/google/registry/model/domain/DesignatedContact.java b/java/google/registry/model/domain/DesignatedContact.java index e15821102..0712f42cf 100644 --- a/java/google/registry/model/domain/DesignatedContact.java +++ b/java/google/registry/model/domain/DesignatedContact.java @@ -52,6 +52,7 @@ public class DesignatedContact extends ImmutableObject { DesignatedContact instance = new DesignatedContact(); instance.type = type; instance.contactId = ReferenceUnion.create(contact); + instance.contact = contact; return instance; } @@ -60,9 +61,12 @@ public class DesignatedContact extends ImmutableObject { @Index @XmlValue - //TODO(b/28713909): Make this a Key. + //TODO(b/28713909): Remove contactId and replace with contact. ReferenceUnion contactId; + @Index + Key contact; + public Type getType() { return type; } diff --git a/java/google/registry/model/domain/DomainBase.java b/java/google/registry/model/domain/DomainBase.java index f574c10a1..9c37eebda 100644 --- a/java/google/registry/model/domain/DomainBase.java +++ b/java/google/registry/model/domain/DomainBase.java @@ -40,6 +40,7 @@ import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.IgnoreSave; import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.OnSave; import com.googlecode.objectify.condition.IfNull; import google.registry.model.EppResource; import google.registry.model.contact.ContactResource; @@ -78,9 +79,13 @@ public abstract class DomainBase extends EppResource { /** References to hosts that are the nameservers for the domain. */ @XmlTransient - //TODO(b/28713909): Make this a Set>. + //TODO(b/28713909): Delete this once migration away from ReferenceUnions is complete. Set> nameservers; + @Index + @XmlTransient + Set> nsHosts; + /** * The union of the contacts visible via {@link #getContacts} and {@link #getRegistrant}. * @@ -234,6 +239,18 @@ public abstract class DomainBase extends EppResource { return tld; } + @OnSave + void dualSaveReferenceUnions() { + for (DesignatedContact contact : nullToEmptyImmutableCopy(allContacts)) { + contact.contact = contact.contactId.getLinked(); + } + ImmutableSet.Builder> hostKeys = new ImmutableSet.Builder<>(); + for (ReferenceUnion refUnion : nullToEmptyImmutableCopy(nameservers)) { + hostKeys.add(refUnion.getLinked()); + } + nsHosts = hostKeys.build(); + } + /** Predicate to determine if a given {@link DesignatedContact} is the registrant. */ private static final Predicate IS_REGISTRANT = new Predicate() { diff --git a/java/google/registry/model/domain/ReferenceUnion.java b/java/google/registry/model/domain/ReferenceUnion.java index 4bfbfcfed..88a7a9395 100644 --- a/java/google/registry/model/domain/ReferenceUnion.java +++ b/java/google/registry/model/domain/ReferenceUnion.java @@ -26,7 +26,9 @@ import google.registry.model.ImmutableObject; * * @param the type being referenced */ +// TODO(b/28713909): Delete ReferenceUnion entirely. @Embed +@Deprecated public class ReferenceUnion extends ImmutableObject { @Index diff --git a/javatests/google/registry/model/domain/DomainApplicationTest.java b/javatests/google/registry/model/domain/DomainApplicationTest.java index 0b0dc389e..c76997ff2 100644 --- a/javatests/google/registry/model/domain/DomainApplicationTest.java +++ b/javatests/google/registry/model/domain/DomainApplicationTest.java @@ -120,8 +120,10 @@ public class DomainApplicationTest extends EntityTestCase { verifyIndexing( domainApplication, "allContacts.contactId.linked", + "allContacts.contact", "fullyQualifiedDomainName", "nameservers.linked", + "nsHosts", "deletionTime", "currentSponsorClientId", "tld"); diff --git a/javatests/google/registry/model/domain/DomainResourceTest.java b/javatests/google/registry/model/domain/DomainResourceTest.java index 9b864e543..3d7bfd4bd 100644 --- a/javatests/google/registry/model/domain/DomainResourceTest.java +++ b/javatests/google/registry/model/domain/DomainResourceTest.java @@ -23,6 +23,8 @@ import static google.registry.testing.DatastoreHelper.cloneAndSetAutoTimestamps; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.newDomainResource; import static google.registry.testing.DatastoreHelper.newHostResource; +import static google.registry.testing.DatastoreHelper.persistActiveContact; +import static google.registry.testing.DatastoreHelper.persistActiveHost; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DomainResourceSubject.assertAboutDomains; import static google.registry.util.DateTimeUtils.START_OF_TIME; @@ -174,8 +176,10 @@ public class DomainResourceTest extends EntityTestCase { verifyIndexing( domain, "allContacts.contactId.linked", + "allContacts.contact", "fullyQualifiedDomainName", "nameservers.linked", + "nsHosts", "currentSponsorClientId", "deletionTime", "tld"); @@ -452,4 +456,27 @@ public class DomainResourceTest extends EntityTestCase { public void testToHydratedString_notCircular() { domain.toHydratedString(); // If there are circular references, this will overflow the stack. } + + // TODO(b/28713909): Remove these tests once ReferenceUnion migration is complete. + @Test + public void testDualSavingOfDesignatedContact() { + ContactResource contact = persistActiveContact("time1006"); + DesignatedContact designatedContact = new DesignatedContact(); + designatedContact.contactId = ReferenceUnion.create(Key.create(contact)); + designatedContact.type = Type.ADMIN; + DomainResource domainWithContact = + domain.asBuilder().setContacts(ImmutableSet.of(designatedContact)).build(); + assertThat(getOnlyElement(domainWithContact.getContacts()).contact).isNull(); + DomainResource reloadedDomain = persistResource(domainWithContact); + assertThat(getOnlyElement(reloadedDomain.getContacts()).contact).isEqualTo(Key.create(contact)); + } + + @Test + public void testDualSavingOfNameservers() { + HostResource host = persistActiveHost("zzz.xxx.yyy"); + DomainResource domain = newDomainResource("python-django-unchained.com", host); + assertThat(domain.nsHosts).isNull(); + DomainResource djangoReloaded = persistResource(domain); + assertThat(djangoReloaded.nsHosts).containsExactly(Key.create(host)); + } } diff --git a/javatests/google/registry/model/schema.txt b/javatests/google/registry/model/schema.txt index dd1006d4c..d76800b6c 100644 --- a/javatests/google/registry/model/schema.txt +++ b/javatests/google/registry/model/schema.txt @@ -187,6 +187,7 @@ enum google.registry.model.contact.PostalInfo$Type { LOCALIZED; } class google.registry.model.domain.DesignatedContact { + com.googlecode.objectify.Key contact; google.registry.model.domain.DesignatedContact$Type type; google.registry.model.domain.ReferenceUnion contactId; } @@ -214,6 +215,7 @@ class google.registry.model.domain.DomainApplication { java.lang.String lastEppUpdateClientId; java.lang.String tld; java.util.List encodedSignedMarks; + java.util.Set> nsHosts; java.util.Set allContacts; java.util.Set> nameservers; java.util.Set dsData; @@ -240,6 +242,7 @@ class google.registry.model.domain.DomainBase { java.lang.String idnTableName; java.lang.String lastEppUpdateClientId; java.lang.String tld; + java.util.Set> nsHosts; java.util.Set allContacts; java.util.Set> nameservers; java.util.Set dsData; @@ -267,6 +270,7 @@ class google.registry.model.domain.DomainResource { java.lang.String lastEppUpdateClientId; java.lang.String smdId; java.lang.String tld; + java.util.Set> nsHosts; java.util.Set allContacts; java.util.Set gracePeriods; java.util.Set> nameservers;