diff --git a/core/src/main/java/google/registry/model/eppcommon/StatusValue.java b/core/src/main/java/google/registry/model/eppcommon/StatusValue.java index c9761eb81..1a1bbc82b 100644 --- a/core/src/main/java/google/registry/model/eppcommon/StatusValue.java +++ b/core/src/main/java/google/registry/model/eppcommon/StatusValue.java @@ -167,10 +167,5 @@ public enum StatusValue implements EppEnum { } /** Hibernate type for sets of {@link StatusValue}. */ - public static class StatusValueSetType extends EnumSetUserType { - @Override - protected StatusValue convertToElem(String value) { - return StatusValue.valueOf(value); - } - } + public static class StatusValueSetType extends EnumSetUserType {} } diff --git a/core/src/main/java/google/registry/model/registrar/RegistrarContact.java b/core/src/main/java/google/registry/model/registrar/RegistrarContact.java index 22d908504..26d1be7af 100644 --- a/core/src/main/java/google/registry/model/registrar/RegistrarContact.java +++ b/core/src/main/java/google/registry/model/registrar/RegistrarContact.java @@ -42,9 +42,14 @@ import google.registry.model.ImmutableObject; import google.registry.model.JsonMapBuilder; import google.registry.model.Jsonifiable; import google.registry.model.annotations.ReportedOn; +import google.registry.persistence.EnumSetUserType; import java.util.Arrays; import java.util.Map; import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.Type; /** * A contact for a Registrar. Note, equality, hashCode and comparable have been overridden to only @@ -56,10 +61,16 @@ import java.util.Set; */ @ReportedOn @Entity +@javax.persistence.Entity +@Table( + name = "RegistrarPoc", + indexes = { + @javax.persistence.Index(columnList = "gaeUserId", name = "registrarpoc_gae_user_id_idx") + }) +// TODO(shicong): Rename the class name to RegistrarPoc after database migration public class RegistrarContact extends ImmutableObject implements Jsonifiable { - @Parent - Key parent; + @Parent @Transient Key parent; /** * Registrar contacts types for partner communication tracking. @@ -92,6 +103,9 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { this.displayName = display; this.required = required; } + + /** Hibernate type for sets of {@link Type}. */ + public static class RegistrarPocType extends EnumSetUserType {} } /** The name of the contact. */ @@ -99,6 +113,8 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { /** The email address of the contact. */ @Id + @javax.persistence.Id + @Column(nullable = false) String emailAddress; /** The voice number of the contact. */ @@ -108,9 +124,11 @@ public class RegistrarContact extends ImmutableObject implements Jsonifiable { String faxNumber; /** - * Multiple types are used to associate the registrar contact with - * various mailing groups. This data is internal to the registry. + * Multiple types are used to associate the registrar contact with various mailing groups. This + * data is internal to the registry. */ + @org.hibernate.annotations.Type( + type = "google.registry.model.registrar.RegistrarContact$Type$RegistrarPocType") Set types; /** diff --git a/core/src/main/java/google/registry/persistence/EnumSetUserType.java b/core/src/main/java/google/registry/persistence/EnumSetUserType.java index d811bfa69..bb3e9ae5d 100644 --- a/core/src/main/java/google/registry/persistence/EnumSetUserType.java +++ b/core/src/main/java/google/registry/persistence/EnumSetUserType.java @@ -14,6 +14,7 @@ package google.registry.persistence; +import google.registry.util.TypeUtils.TypeInstantiator; import java.util.HashSet; import java.util.Set; @@ -35,4 +36,16 @@ public class EnumSetUserType> public Class returnedClass() { return Set.class; } + + @Override + protected E convertToElem(String columnValue) { + return columnValue == null + ? null + : Enum.valueOf(new TypeInstantiator(getClass()) {}.getExactType(), columnValue); + } + + @Override + protected String convertToColumn(E elementValue) { + return elementValue == null ? null : elementValue.toString(); + } } diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index 27d763139..dd0f85838 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -21,6 +21,7 @@ --> google.registry.model.domain.DomainBase google.registry.model.registrar.Registrar + google.registry.model.registrar.RegistrarContact google.registry.schema.domain.RegistryLock google.registry.schema.tmch.ClaimsList google.registry.schema.cursor.Cursor diff --git a/core/src/test/java/google/registry/persistence/EnumSetUserTypeTest.java b/core/src/test/java/google/registry/persistence/EnumSetUserTypeTest.java index 888808c69..966156b10 100644 --- a/core/src/test/java/google/registry/persistence/EnumSetUserTypeTest.java +++ b/core/src/test/java/google/registry/persistence/EnumSetUserTypeTest.java @@ -49,17 +49,33 @@ public class EnumSetUserTypeTest { assertThat(persisted.data).isEqualTo(enums); } + @Test + public void testNativeQuery_succeeds() { + Set enums = ImmutableSet.of(TestEnum.BAR, TestEnum.FOO); + TestEntity obj = new TestEntity("foo", enums); + + jpaTm().transact(() -> jpaTm().getEntityManager().persist(obj)); + + assertThat( + ImmutableSet.of( + getSingleResultFromNativeQuery( + "SELECT data[1] FROM \"TestEntity\" WHERE name = 'foo'"), + getSingleResultFromNativeQuery( + "SELECT data[2] FROM \"TestEntity\" WHERE name = 'foo'"))) + .containsExactly("BAR", "FOO"); + } + + private static Object getSingleResultFromNativeQuery(String sql) { + return jpaTm() + .transact(() -> jpaTm().getEntityManager().createNativeQuery(sql).getSingleResult()); + } + enum TestEnum { FOO, BAR, BAZ; - public static class TestEnumType extends EnumSetUserType { - @Override - protected TestEnum convertToElem(String value) { - return TestEnum.valueOf(value); - } - } + public static class TestEnumType extends EnumSetUserType {} } @Entity(name = "TestEntity") diff --git a/db/src/main/resources/sql/flyway/V17__create_registrar_poc.sql b/db/src/main/resources/sql/flyway/V17__create_registrar_poc.sql new file mode 100644 index 000000000..f79bdb4f0 --- /dev/null +++ b/db/src/main/resources/sql/flyway/V17__create_registrar_poc.sql @@ -0,0 +1,31 @@ +-- Copyright 2020 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. + +create table "RegistrarPoc" ( + email_address text not null, + allowed_to_set_registry_lock_password boolean not null, + fax_number text, + gae_user_id text, + name text, + phone_number text, + registry_lock_password_hash text, + registry_lock_password_salt text, + types text[], + visible_in_domain_whois_as_abuse boolean not null, + visible_in_whois_as_admin boolean not null, + visible_in_whois_as_tech boolean not null, + primary key (email_address) + ); + +create index registrarpoc_gae_user_id_idx on "RegistrarPoc" (gae_user_id); diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index 1dfa65b65..c57b245fb 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -142,6 +142,22 @@ primary key (client_id) ); + create table "RegistrarPoc" ( + email_address text not null, + allowed_to_set_registry_lock_password boolean not null, + fax_number text, + gae_user_id text, + name text, + phone_number text, + registry_lock_password_hash text, + registry_lock_password_salt text, + types text[], + visible_in_domain_whois_as_abuse boolean not null, + visible_in_whois_as_admin boolean not null, + visible_in_whois_as_tech boolean not null, + primary key (email_address) + ); + create table "RegistryLock" ( revision_id bigserial not null, domain_name text not null, @@ -181,6 +197,7 @@ create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld); create index premiumlist_name_idx on "PremiumList" (name); create index registrar_name_idx on "Registrar" (registrar_name); create index registrar_iana_identifier_idx on "Registrar" (iana_identifier); +create index registrarpoc_gae_user_id_idx on "RegistrarPoc" (gae_user_id); create index idx_registry_lock_verification_code on "RegistryLock" (verification_code); create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id); diff --git a/db/src/main/resources/sql/schema/nomulus.golden.sql b/db/src/main/resources/sql/schema/nomulus.golden.sql index b75c768d5..feb1f2f6b 100644 --- a/db/src/main/resources/sql/schema/nomulus.golden.sql +++ b/db/src/main/resources/sql/schema/nomulus.golden.sql @@ -212,6 +212,26 @@ CREATE TABLE public."Registrar" ( ); +-- +-- Name: RegistrarPoc; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public."RegistrarPoc" ( + email_address text NOT NULL, + allowed_to_set_registry_lock_password boolean NOT NULL, + fax_number text, + gae_user_id text, + name text, + phone_number text, + registry_lock_password_hash text, + registry_lock_password_salt text, + types text[], + visible_in_domain_whois_as_abuse boolean NOT NULL, + visible_in_whois_as_admin boolean NOT NULL, + visible_in_whois_as_tech boolean NOT NULL +); + + -- -- Name: RegistryLock; Type: TABLE; Schema: public; Owner: - -- @@ -370,6 +390,14 @@ ALTER TABLE ONLY public."PremiumList" ADD CONSTRAINT "PremiumList_pkey" PRIMARY KEY (revision_id); +-- +-- Name: RegistrarPoc RegistrarPoc_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public."RegistrarPoc" + ADD CONSTRAINT "RegistrarPoc_pkey" PRIMARY KEY (email_address); + + -- -- Name: Registrar Registrar_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -480,6 +508,13 @@ CREATE INDEX registrar_iana_identifier_idx ON public."Registrar" USING btree (ia CREATE INDEX registrar_name_idx ON public."Registrar" USING btree (registrar_name); +-- +-- Name: registrarpoc_gae_user_id_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX registrarpoc_gae_user_id_idx ON public."RegistrarPoc" USING btree (gae_user_id); + + -- -- Name: reservedlist_name_idx; Type: INDEX; Schema: public; Owner: - --