mirror of
https://github.com/google/nomulus.git
synced 2025-07-26 04:28:34 +02:00
Add annotation processor to generate converter for VKey (#566)
This commit is contained in:
parent
d3df6bcb52
commit
0bf8c45102
44 changed files with 695 additions and 51 deletions
|
@ -135,7 +135,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
|||
@Transient
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions = ImmutableSortedMap.of();
|
||||
|
||||
public final String getRepoId() {
|
||||
public String getRepoId() {
|
||||
return repoId;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@ import javax.annotation.Nullable;
|
|||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.JoinTable;
|
||||
|
@ -147,7 +146,6 @@ public class DomainBase extends EppResource
|
|||
@Ignore
|
||||
@ElementCollection
|
||||
@JoinTable(name = "DomainHost")
|
||||
@Convert(converter = HostResource.VKeyHostResourceConverter.class)
|
||||
Set<VKey<HostResource>> nsHostVKeys;
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,7 +34,7 @@ import google.registry.model.annotations.ReportedOn;
|
|||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.converter.VKeyConverter;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -54,6 +54,7 @@ import org.joda.time.DateTime;
|
|||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@ExternalMessagingName("host")
|
||||
@WithStringVKey
|
||||
public class HostResource extends EppResource implements ForeignKeyedEppResource {
|
||||
|
||||
/**
|
||||
|
@ -212,11 +213,4 @@ public class HostResource extends EppResource implements ForeignKeyedEppResource
|
|||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VKeyHostResourceConverter extends VKeyConverter<HostResource> {
|
||||
@Override
|
||||
protected Class<HostResource> getAttributeClass() {
|
||||
return HostResource.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.util.Optional;
|
||||
|
@ -41,20 +42,31 @@ public class VKey<T> extends ImmutableObject {
|
|||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
public static <T> VKey<T> createSql(Class<? extends T> kind, Object primaryKey) {
|
||||
return new VKey(kind, null, primaryKey);
|
||||
/** Creates a {@link VKey} which only contains the sql primary key. */
|
||||
public static <T> VKey<T> createSql(Class<? extends T> kind, Object sqlKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(sqlKey, "sqlKey must not be null");
|
||||
return new VKey(kind, null, sqlKey);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} which only contains the ofy primary key. */
|
||||
public static <T> VKey<T> createOfy(
|
||||
Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey) {
|
||||
Class<? extends T> kind, com.googlecode.objectify.Key<? extends T> ofyKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(ofyKey, "ofyKey must not be null");
|
||||
return new VKey(kind, ofyKey, null);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} which only contains both sql and ofy primary key. */
|
||||
public static <T> VKey<T> create(
|
||||
Class<? extends T> kind, Object primaryKey, com.googlecode.objectify.Key ofyKey) {
|
||||
return new VKey(kind, ofyKey, primaryKey);
|
||||
Class<? extends T> kind, Object sqlKey, com.googlecode.objectify.Key ofyKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(sqlKey, "sqlKey must not be null");
|
||||
checkArgumentNotNull(ofyKey, "ofyKey must not be null");
|
||||
return new VKey(kind, ofyKey, sqlKey);
|
||||
}
|
||||
|
||||
/** Returns the type of the entity. */
|
||||
public Class<? extends T> getKind() {
|
||||
return this.kind;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// 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.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* Annotation for {@link Entity} which id is long type and needs an {@link AttributeConverter} for
|
||||
* its VKey.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface WithLongVKey {
|
||||
/**
|
||||
* Sets the suffix of the class name for the {@link AttributeConverter} generated by
|
||||
* LongVKeyProcessor. If not set, the suffix will be the type name of the VKey. Note that the
|
||||
* class name will be "VKeyConverter_" concatenated with the suffix.
|
||||
*/
|
||||
String classNameSuffix() default "";
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// 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.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* Annotation for {@link Entity} which id is string type and needs an {@link AttributeConverter} for
|
||||
* its VKey.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface WithStringVKey {
|
||||
/**
|
||||
* Sets the suffix of the class name for the {@link AttributeConverter} generated by
|
||||
* StringVKeyProcessor. If not set, the suffix will be the type name of the VKey. Note that the
|
||||
* class name will be "VKeyConverter_" concatenated with the suffix.
|
||||
*/
|
||||
String classNameSuffix() default "";
|
||||
}
|
|
@ -19,16 +19,16 @@ import javax.annotation.Nullable;
|
|||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/** Converts VKey to a string column. */
|
||||
public abstract class VKeyConverter<T> implements AttributeConverter<VKey<T>, String> {
|
||||
public abstract class VKeyConverter<T, C> implements AttributeConverter<VKey<? extends T>, C> {
|
||||
@Override
|
||||
@Nullable
|
||||
public String convertToDatabaseColumn(@Nullable VKey<T> attribute) {
|
||||
return attribute == null ? null : (String) attribute.getSqlKey();
|
||||
public C convertToDatabaseColumn(@Nullable VKey<? extends T> attribute) {
|
||||
return attribute == null ? null : (C) attribute.getSqlKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public VKey<T> convertToEntityAttribute(@Nullable String dbData) {
|
||||
public VKey<? extends T> convertToEntityAttribute(@Nullable C dbData) {
|
||||
return dbData == null ? null : VKey.createSql(getAttributeClass(), dbData);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
<class>google.registry.persistence.converter.StringListConverter</class>
|
||||
<class>google.registry.persistence.converter.StringSetConverter</class>
|
||||
<class>google.registry.persistence.converter.UpdateAutoTimestampConverter</class>
|
||||
<class>google.registry.persistence.converter.VKeyConverter</class>
|
||||
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
|
||||
|
||||
<!-- Generated converters for VKey -->
|
||||
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
||||
|
||||
<!-- TODO(weiminyu): check out application-layer validation. -->
|
||||
<validation-mode>NONE</validation-mode>
|
||||
</persistence-unit>
|
||||
|
|
|
@ -37,9 +37,10 @@ public class VKeyTest {
|
|||
|
||||
@Test
|
||||
public void testOptionalAccessors() {
|
||||
VKey<TestObject> key = VKey.create(TestObject.class, null, null);
|
||||
assertThat(key.maybeGetSqlKey().isPresent()).isFalse();
|
||||
assertThat(key.maybeGetOfyKey().isPresent()).isFalse();
|
||||
VKey<TestObject> key =
|
||||
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo")));
|
||||
assertThat(key.maybeGetSqlKey().isPresent()).isTrue();
|
||||
assertThat(key.maybeGetOfyKey().isPresent()).isTrue();
|
||||
|
||||
Key<TestObject> ofyKey = Key.create(TestObject.create("foo"));
|
||||
assertThat(VKey.createOfy(TestObject.class, ofyKey).maybeGetOfyKey().get()).isEqualTo(ofyKey);
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
// 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.
|
||||
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithLongVKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Test SQL persistence of VKey. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class LongVKeyConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaUnitTestRule jpaRule =
|
||||
new JpaTestRules.Builder()
|
||||
.withEntityClass(TestEntity.class, VKeyConverter_LongType.class)
|
||||
.buildUnitTestRule();
|
||||
|
||||
@Test
|
||||
public void testRoundTrip() {
|
||||
TestEntity original = new TestEntity(VKey.createSql(TestEntity.class, 10L));
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(original));
|
||||
|
||||
TestEntity retrieved =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(retrieved.number.getSqlKey()).isEqualTo(10L);
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
@WithLongVKey(classNameSuffix = "LongType")
|
||||
static class TestEntity {
|
||||
@Id String id = "id";
|
||||
|
||||
VKey<TestEntity> number;
|
||||
|
||||
TestEntity(VKey<TestEntity> number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
/** Default constructor, needed for hibernate. */
|
||||
public TestEntity() {}
|
||||
}
|
||||
}
|
|
@ -18,9 +18,9 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.junit.Rule;
|
||||
|
@ -30,13 +30,15 @@ import org.junit.runners.JUnit4;
|
|||
|
||||
/** Test SQL persistence of VKey. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class VKeyConverterTest {
|
||||
public class StringVKeyConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaUnitTestRule jpaRule =
|
||||
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
|
||||
new JpaTestRules.Builder()
|
||||
.withEntityClass(TestEntity.class, VKeyConverter_StringType.class)
|
||||
.buildUnitTestRule();
|
||||
|
||||
public VKeyConverterTest() {}
|
||||
public StringVKeyConverterTest() {}
|
||||
|
||||
@Test
|
||||
public void testRoundTrip() {
|
||||
|
@ -50,21 +52,11 @@ public class VKeyConverterTest {
|
|||
assertThat(retrieved.other.getSqlKey()).isEqualTo("ImSpartacus!");
|
||||
}
|
||||
|
||||
static class TestEntityVKeyConverter extends VKeyConverter<TestEntity> {
|
||||
|
||||
@Override
|
||||
protected Class<TestEntity> getAttributeClass() {
|
||||
return TestEntity.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
@WithStringVKey(classNameSuffix = "StringType")
|
||||
static class TestEntity {
|
||||
@Id String id;
|
||||
|
||||
// Specifying "@Converter(autoApply = true) on TestEntityVKeyConverter this doesn't seem to
|
||||
// work.
|
||||
@Convert(converter = TestEntityVKeyConverter.class)
|
||||
VKey<TestEntity> other;
|
||||
|
||||
TestEntity(String id, VKey<TestEntity> other) {
|
Loading…
Add table
Add a link
Reference in a new issue