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;