mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
Remove references to Objectify (#1846)
This is not a complete removal of ofy as we still a dependency on it (GaeUserIdConverter). But this PR removed it from a lot of places where it's no longer needed.
This commit is contained in:
parent
b578060c66
commit
cc451bb7dc
53 changed files with 82 additions and 921 deletions
|
@ -55,8 +55,6 @@ public class JpaDemoPipeline implements Serializable {
|
|||
|
||||
@ProcessElement
|
||||
public void processElement() {
|
||||
// AppEngineEnvironment is needed as long as JPA entity classes still depends
|
||||
// on Objectify.
|
||||
int result =
|
||||
(Integer)
|
||||
jpaTm()
|
||||
|
|
|
@ -64,7 +64,7 @@ public abstract class BillingEvent implements Serializable {
|
|||
"amount",
|
||||
"flags");
|
||||
|
||||
/** Returns the unique Objectify ID for the {@code OneTime} associated with this event. */
|
||||
/** Returns the unique ID for the {@code OneTime} associated with this event. */
|
||||
abstract long id();
|
||||
|
||||
/** Returns the UTC DateTime this event becomes billable. */
|
||||
|
|
|
@ -29,12 +29,12 @@ import google.registry.flows.EppException.SyntaxErrorException;
|
|||
import google.registry.flows.EppException.UnimplementedProtocolVersionException;
|
||||
import google.registry.flows.custom.EntityChanges;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.adapters.CurrencyUnitAdapter.UnknownCurrencyException;
|
||||
import google.registry.model.eppcommon.EppXmlTransformer;
|
||||
import google.registry.model.eppinput.EppInput.WrongProtocolVersionException;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
import google.registry.model.host.InetAddressAdapter.IpVersionMismatchException;
|
||||
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
|
||||
import google.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException;
|
||||
import google.registry.xml.XmlException;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
import static google.registry.model.IdService.allocateId;
|
||||
import static google.registry.model.ModelUtils.getAllFields;
|
||||
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -56,14 +55,10 @@ public interface Buildable {
|
|||
/** Build the instance. */
|
||||
public S build() {
|
||||
try {
|
||||
// If this object has a Long or long Objectify @Id field that is not set, set it now. For
|
||||
// any entity it has one and only one @Id field in its class hierarchy.
|
||||
// If this object has a Long or long @OfyIdAllocation field that is not set, set it now.
|
||||
Field idField =
|
||||
getAllFields(instance.getClass()).values().stream()
|
||||
.filter(
|
||||
field ->
|
||||
field.isAnnotationPresent(Id.class)
|
||||
|| field.isAnnotationPresent(OfyIdAllocation.class))
|
||||
.filter(field -> field.isAnnotationPresent(OfyIdAllocation.class))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (idField != null
|
||||
|
|
|
@ -21,8 +21,6 @@ import static java.util.stream.Collectors.toCollection;
|
|||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
@ -76,7 +74,7 @@ public abstract class ImmutableObject implements Cloneable {
|
|||
// Note: if this class is made to implement Serializable, this field must become 'transient' since
|
||||
// hashing is not stable across executions. Also note that @XmlTransient is forbidden on transient
|
||||
// fields and need to be removed if transient is added.
|
||||
@Ignore @XmlTransient protected Integer hashCode;
|
||||
@XmlTransient protected Integer hashCode;
|
||||
|
||||
private boolean equalsImmutableObject(ImmutableObject other) {
|
||||
return getClass().equals(other.getClass())
|
||||
|
@ -176,9 +174,6 @@ public abstract class ImmutableObject implements Cloneable {
|
|||
|
||||
/** Helper function to recursively hydrate an ImmutableObject. */
|
||||
private static Object hydrate(Object value) {
|
||||
if (value instanceof Key) {
|
||||
return value;
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
return transformValues((Map<?, ?>) value, ImmutableObject::hydrate);
|
||||
}
|
||||
|
|
|
@ -25,22 +25,13 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -49,7 +40,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** A collection of static methods that deal with reflection on model classes. */
|
||||
|
@ -86,84 +76,6 @@ public class ModelUtils {
|
|||
return ALL_FIELDS_CACHE.get(clazz);
|
||||
}
|
||||
|
||||
/** Return a string representing the persisted schema of a type or enum. */
|
||||
static String getSchema(Class<?> clazz) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Stream<?> body;
|
||||
if (clazz.isEnum()) {
|
||||
stringBuilder.append("enum ");
|
||||
body = Arrays.stream(clazz.getEnumConstants());
|
||||
} else {
|
||||
stringBuilder.append("class ");
|
||||
body =
|
||||
getAllFields(clazz)
|
||||
.values()
|
||||
.stream()
|
||||
.filter(field -> !field.isAnnotationPresent(Ignore.class))
|
||||
.map(
|
||||
field -> {
|
||||
String annotation =
|
||||
field.isAnnotationPresent(Id.class)
|
||||
? "@Id "
|
||||
: field.isAnnotationPresent(Parent.class) ? "@Parent " : "";
|
||||
String type =
|
||||
field.getType().isArray()
|
||||
? field.getType().getComponentType().getName() + "[]"
|
||||
: field.getGenericType().toString().replaceFirst("class ", "");
|
||||
return String.format("%s%s %s", annotation, type, field.getName());
|
||||
});
|
||||
}
|
||||
return stringBuilder
|
||||
.append(clazz.getName())
|
||||
.append(" {\n ")
|
||||
.append(body.map(Object::toString).sorted().collect(Collectors.joining(";\n ")))
|
||||
.append(";\n}")
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of Class objects of all persisted fields. This includes the parameterized
|
||||
* type(s) of any fields (if any).
|
||||
*/
|
||||
static Set<Class<?>> getPersistedFieldTypes(Class<?> clazz) {
|
||||
ImmutableSet.Builder<Class<?>> builder = new ImmutableSet.Builder<>();
|
||||
for (Field field : getAllFields(clazz).values()) {
|
||||
// Skip fields that aren't persisted to Datastore.
|
||||
if (field.isAnnotationPresent(Ignore.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the field's type is the same as the field's class object, then it's a non-parameterized
|
||||
// type, and thus we just add it directly. We also don't bother looking at the parameterized
|
||||
// types of Key and VKey objects, since they are just references to other objects and don't
|
||||
// actually embed themselves in the persisted object anyway.
|
||||
Class<?> fieldClazz = field.getType();
|
||||
Type fieldType = field.getGenericType();
|
||||
if (VKey.class.equals(fieldClazz)) {
|
||||
continue;
|
||||
}
|
||||
builder.add(fieldClazz);
|
||||
if (fieldType.equals(fieldClazz) || Key.class.equals(clazz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the field is a parameterized type, then also add the parameterized field.
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
|
||||
for (Type actualType : parameterizedType.getActualTypeArguments()) {
|
||||
if (actualType instanceof Class<?>) {
|
||||
builder.add((Class<?>) actualType);
|
||||
} else {
|
||||
// We intentionally ignore types that are parameterized on non-concrete types. In theory
|
||||
// we could have collections embedded within collections, but Objectify does not allow
|
||||
// that.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/** Retrieves a field value via reflection. */
|
||||
static Object getFieldValue(Object instance, Field field) {
|
||||
try {
|
||||
|
|
|
@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableSet;
|
|||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
|
@ -199,9 +198,8 @@ public final class OteAccountBuilder {
|
|||
*
|
||||
* <p>Use this to set up registrar fields.
|
||||
*
|
||||
* <p>NOTE: DO NOT change anything that would affect the {@link Key#create} result on Registrars.
|
||||
* If you want to make this function public, add a check that the Key.create on the registrars
|
||||
* hasn't changed.
|
||||
* <p>NOTE: DO NOT change anything that would affect the result of {@link Registrar#createVKey()}
|
||||
* . If you want to make this function public, add a check that the value hasn't changed.
|
||||
*
|
||||
* @param func a function setting the requested fields on Registrar Builders. Will be applied to
|
||||
* all the Registrars.
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.google.common.collect.HashMultiset;
|
|||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.domain.DomainCommand;
|
||||
import google.registry.model.domain.fee.FeeCreateCommandExtension;
|
||||
import google.registry.model.domain.launch.LaunchCreateExtension;
|
||||
|
@ -202,7 +201,7 @@ public class OteStats {
|
|||
try {
|
||||
record(historyEntry);
|
||||
} catch (XmlException e) {
|
||||
throw new RuntimeException("Couldn't parse history entry " + Key.create(historyEntry), e);
|
||||
throw new RuntimeException("Couldn't parse history entry " + historyEntry.createVKey(), e);
|
||||
}
|
||||
// Break out early if all tests were passed.
|
||||
if (wereAllTestsPassed()) {
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.io.Serializable;
|
|||
* the migration. Note that only objects loaded from the SQL database need serialization support.
|
||||
*
|
||||
* <p>All entities implementing this interface take advantage of the fact that all Java collection
|
||||
* classes we use, either directly or indirectly, including those in Java libraries, Guava,
|
||||
* Objectify, and Hibernate are {@code Serializable}.
|
||||
* classes we use, either directly or indirectly, including those in Java libraries, Guava, and
|
||||
* Hibernate are {@code Serializable}.
|
||||
*
|
||||
* <p>The {@code serialVersionUID} field has also been omitted in the implementing classes, since
|
||||
* they are not used for persistence.
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
package google.registry.model;
|
||||
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.util.PreconditionsUtils;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
|
@ -39,7 +38,6 @@ public abstract class UpdateAutoTimestampEntity extends ImmutableObject
|
|||
// Prevents subclasses from unexpectedly accessing as property (e.g., Host), which would
|
||||
// require an unnecessary non-private setter method.
|
||||
@Access(AccessType.FIELD)
|
||||
@Ignore
|
||||
UpdateAutoTimestamp updateTimestamp = UpdateAutoTimestamp.create(null);
|
||||
|
||||
/** Get the {@link UpdateAutoTimestamp} for this entity. */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright 2017 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.model.annotations;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation for an Objectify {@link Entity} to indicate that it should be exported to BigQuery.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface ReportedOn {}
|
|
@ -29,7 +29,6 @@ import google.registry.model.Buildable;
|
|||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.TimeOfYear;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
|
@ -594,7 +593,6 @@ public abstract class BillingEvent extends ImmutableObject
|
|||
* <p>This is implemented as a separate event rather than a bit on BillingEvent in order to
|
||||
* preserve the immutability of billing events.
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity(name = "BillingCancellation")
|
||||
@Table(
|
||||
indexes = {
|
||||
|
|
|
@ -25,7 +25,6 @@ import static org.joda.time.DateTimeZone.UTC;
|
|||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ContiguousSet;
|
||||
import com.google.common.collect.Range;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import java.util.List;
|
||||
|
@ -50,7 +49,6 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
|
|||
* The time as "month day millis" with all fields left-padded with zeroes so that lexographic
|
||||
* sorting will do the right thing.
|
||||
*/
|
||||
@Index
|
||||
String timeString;
|
||||
|
||||
/**
|
||||
|
|
|
@ -241,8 +241,8 @@ public class ContactBase extends EppResource
|
|||
* 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
|
||||
* persist them directly due to legacy reasons (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")
|
||||
|
|
|
@ -16,7 +16,6 @@ package google.registry.model.domain;
|
|||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.contact.Contact;
|
||||
|
@ -69,7 +68,7 @@ public class DesignatedContact extends ImmutableObject implements UnsafeSerializ
|
|||
|
||||
Type type;
|
||||
|
||||
@Ignore VKey<Contact> contactVKey;
|
||||
VKey<Contact> contactVKey;
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
|
|
|
@ -18,7 +18,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
|||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.domain.GracePeriod.GracePeriodHistory;
|
||||
import google.registry.model.domain.secdns.DomainDsData;
|
||||
|
@ -115,7 +114,6 @@ public class DomainHistory extends HistoryEntry {
|
|||
updatable = false)
|
||||
})
|
||||
// HashSet rather than ImmutableSet so that Hibernate can fill them out lazily on request
|
||||
@Ignore
|
||||
Set<DomainDsDataHistory> dsDataHistories = new HashSet<>();
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
|
||||
package google.registry.model.domain.fee06;
|
||||
|
||||
import google.registry.model.translators.CurrencyUnitAdapter;
|
||||
import google.registry.model.adapters.CurrencyUnitAdapter;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlNs;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
|
||||
package google.registry.model.domain.fee11;
|
||||
|
||||
import google.registry.model.translators.CurrencyUnitAdapter;
|
||||
import google.registry.model.adapters.CurrencyUnitAdapter;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlNs;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)})
|
||||
package google.registry.model.domain.fee12;
|
||||
|
||||
import google.registry.model.translators.CurrencyUnitAdapter;
|
||||
import google.registry.model.adapters.CurrencyUnitAdapter;
|
||||
import google.registry.xml.UtcDateTimeAdapter;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
|
|
|
@ -17,8 +17,8 @@ package google.registry.model.domain.rgp;
|
|||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.model.adapters.EnumToAttributeAdapter;
|
||||
import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
|
|
@ -20,14 +20,14 @@ import static com.google.common.base.Strings.nullToEmpty;
|
|||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.model.adapters.StatusValueAdapter;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostBase;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.model.translators.StatusValueAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,26 +14,26 @@
|
|||
|
||||
package google.registry.model.host;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithVKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persistable Host resource including mutable and non-mutable fields.
|
||||
*
|
||||
* <p>The {@link javax.persistence.Id} of the Host is the repoId.
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "Host")
|
||||
@javax.persistence.Table(
|
||||
@Entity(name = "Host")
|
||||
@Table(
|
||||
name = "Host",
|
||||
/**
|
||||
/*
|
||||
* A gin index defined on the inet_addresses field ({@link HostBase#inetAddresses} cannot be
|
||||
* declared here because JPA/Hibernate does not support index type specification. As a result,
|
||||
* the hibernate-generated schema (which is for reference only) does not have this index.
|
||||
|
@ -45,10 +45,10 @@ import javax.persistence.AccessType;
|
|||
* doing either.
|
||||
*/
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "hostName"),
|
||||
@javax.persistence.Index(columnList = "creationTime"),
|
||||
@javax.persistence.Index(columnList = "deletionTime"),
|
||||
@javax.persistence.Index(columnList = "currentSponsorRegistrarId")
|
||||
@Index(columnList = "hostName"),
|
||||
@Index(columnList = "creationTime"),
|
||||
@Index(columnList = "deletionTime"),
|
||||
@Index(columnList = "currentSponsorRegistrarId")
|
||||
})
|
||||
@ExternalMessagingName("host")
|
||||
@WithVKey(String.class)
|
||||
|
@ -56,7 +56,7 @@ import javax.persistence.AccessType;
|
|||
public class Host extends HostBase implements ForeignKeyedEppResource {
|
||||
|
||||
@Override
|
||||
@javax.persistence.Id
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY) // to tell it to use the non-default property-as-ID
|
||||
public String getRepoId() {
|
||||
return super.getRepoId();
|
||||
|
|
|
@ -21,27 +21,17 @@ import static google.registry.util.TypeUtils.hasAnnotation;
|
|||
|
||||
import com.google.appengine.api.datastore.AsyncDatastoreService;
|
||||
import com.google.appengine.api.datastore.DatastoreServiceConfig;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Objectify;
|
||||
import com.googlecode.objectify.ObjectifyFactory;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.impl.translate.TranslatorFactory;
|
||||
import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
|
||||
import google.registry.model.translators.CidrAddressBlockTranslatorFactory;
|
||||
import google.registry.model.translators.CurrencyUnitTranslatorFactory;
|
||||
import google.registry.model.translators.DurationTranslatorFactory;
|
||||
import google.registry.model.translators.InetAddressTranslatorFactory;
|
||||
import google.registry.model.translators.ReadableInstantUtcTranslatorFactory;
|
||||
|
||||
/**
|
||||
* An instance of Ofy, obtained via {@code #auditedOfy()}, should be used to access all persistable
|
||||
|
@ -86,11 +76,6 @@ public class ObjectifyService {
|
|||
// The "false" argument means that we are not using the v5-style Objectify embedded entities.
|
||||
com.googlecode.objectify.ObjectifyService.setFactory(
|
||||
new ObjectifyFactory(false) {
|
||||
@Override
|
||||
public Objectify begin() {
|
||||
return new SessionKeyExposingObjectify(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AsyncDatastoreService createRawAsyncDatastoreService(
|
||||
DatastoreServiceConfig cfg) {
|
||||
|
@ -103,26 +88,9 @@ public class ObjectifyService {
|
|||
}
|
||||
});
|
||||
|
||||
// Translators must be registered before any entities can be registered.
|
||||
registerTranslators();
|
||||
registerEntityClasses(ImmutableSet.of(GaeUserIdConverter.class));
|
||||
}
|
||||
|
||||
/** Register translators that allow less common types to be stored directly in Datastore. */
|
||||
private static void registerTranslators() {
|
||||
for (TranslatorFactory<?> translatorFactory :
|
||||
ImmutableList.of(
|
||||
new BloomFilterOfStringTranslatorFactory(),
|
||||
new CidrAddressBlockTranslatorFactory(),
|
||||
new CurrencyUnitTranslatorFactory(),
|
||||
new DurationTranslatorFactory(),
|
||||
new InetAddressTranslatorFactory(),
|
||||
new MoneyStringTranslatorFactory(),
|
||||
new ReadableInstantUtcTranslatorFactory())) {
|
||||
factory().getTranslators().add(translatorFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/** Register classes that can be persisted via Objectify as Datastore entities. */
|
||||
private static void registerEntityClasses(
|
||||
ImmutableSet<Class<? extends ImmutableObject>> entityClasses) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import com.google.appengine.api.datastore.DatastoreTimeoutException;
|
|||
import com.google.appengine.api.taskqueue.TransientFailureException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
|
@ -97,16 +96,6 @@ public class Ofy {
|
|||
return ofy().factory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns keys read by Objectify during this transaction.
|
||||
*
|
||||
* <p>This won't include the keys of asynchronous save and delete operations that haven't been
|
||||
* reaped.
|
||||
*/
|
||||
public ImmutableSet<Key<?>> getSessionKeys() {
|
||||
return ((SessionKeyExposingObjectify) ofy()).getSessionKeys();
|
||||
}
|
||||
|
||||
/** Clears the session cache. */
|
||||
public void clearSessionCache() {
|
||||
ofy().clear();
|
||||
|
@ -272,7 +261,6 @@ public class Ofy {
|
|||
});
|
||||
return work.getResult();
|
||||
} catch (TransientFailureException
|
||||
| TimestampInversionException
|
||||
| DatastoreTimeoutException
|
||||
| DatastoreFailureException e) {
|
||||
// TransientFailureExceptions come from task queues and always mean nothing committed.
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2017 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.model.ofy;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyFactory;
|
||||
import com.googlecode.objectify.impl.ObjectifyImpl;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
|
||||
/** Registry-specific Objectify subclass that exposes the keys used in the current session. */
|
||||
@DeleteAfterMigration
|
||||
public class SessionKeyExposingObjectify extends ObjectifyImpl<SessionKeyExposingObjectify> {
|
||||
|
||||
public SessionKeyExposingObjectify(ObjectifyFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
/** Expose the protected method that provides the keys read, saved or deleted in a session. */
|
||||
ImmutableSet<Key<?>> getSessionKeys() {
|
||||
return ImmutableSet.copyOf(getSession().keys());
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright 2017 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.model.ofy;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Objectify;
|
||||
import google.registry.model.UpdateAutoTimestampEntity;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Exception when trying to write to Datastore with a timestamp that is inconsistent with a partial
|
||||
* ordering on transactions that touch the same entities.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
class TimestampInversionException extends RuntimeException {
|
||||
|
||||
static String getFileAndLine(StackTraceElement callsite) {
|
||||
return callsite.getFileName() + ":" + callsite.getLineNumber();
|
||||
}
|
||||
|
||||
TimestampInversionException(
|
||||
DateTime transactionTime, Map<Key<UpdateAutoTimestampEntity>, DateTime> problematicRoots) {
|
||||
this(transactionTime, "entities rooted under:\n" + problematicRoots);
|
||||
}
|
||||
|
||||
TimestampInversionException(DateTime transactionTime, DateTime updateTimestamp) {
|
||||
this(transactionTime, String.format("update timestamp (%s)", updateTimestamp));
|
||||
}
|
||||
|
||||
private TimestampInversionException(DateTime transactionTime, String problem) {
|
||||
super(
|
||||
String.format(
|
||||
"Timestamp inversion between transaction time (%s) and %s\n%s",
|
||||
transactionTime,
|
||||
problem,
|
||||
getFileAndLine(
|
||||
Arrays.stream(new Exception().getStackTrace())
|
||||
.filter(
|
||||
element ->
|
||||
!element
|
||||
.getClassName()
|
||||
.startsWith(Objectify.class.getPackage().getName())
|
||||
&& !element.getClassName().startsWith(Ofy.class.getName()))
|
||||
.findFirst()
|
||||
.get())));
|
||||
}
|
||||
}
|
|
@ -29,22 +29,21 @@ import javax.xml.bind.annotation.XmlSchema;
|
|||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/*
|
||||
* This package defines all entities which are managed via EPP XML and persisted to the Datastore
|
||||
* via Objectify.
|
||||
* This package defines all entities which are managed via EPP XML and persisted to SQL via
|
||||
* Hibernate.
|
||||
*
|
||||
* <p>All first class entities are represented as a resource class - {@link
|
||||
* google.registry.model.domain.Domain}, {@link google.registry.model.host.Host}, {@link
|
||||
* google.registry.model.contact.Contact}, and {@link
|
||||
* google.registry.model.registrar.Registrar}. Resource objects are written in a single shared
|
||||
* entity group per TLD. All commands that operate on those entities are grouped in a "Command"
|
||||
* class- {@link google.registry.model.domain.DomainCommand}, {@link
|
||||
* google.registry.model.registrar.Registrar}. All commands that operate on those entities are
|
||||
* grouped in a "Command" class- {@link google.registry.model.domain.DomainCommand}, {@link
|
||||
* google.registry.model.host.HostCommand}, {@link google.registry.model.contact.ContactCommand}.
|
||||
* The Resource does double duty as both the persisted representation and as the XML-marshallable
|
||||
* object returned in respond to Info commands.
|
||||
*
|
||||
* <p>Command classes are never persisted, and the Objectify annotations on the Create and Update
|
||||
* classes are purely for the benefit of the derived Resource classes that inherit from them.
|
||||
* Whenever a command that mutates the model is executed, a HistoryEvent is stored with the affected
|
||||
* Resource as its Datastore parent. All history entries have an indexed modification time field so
|
||||
* that the history can be read in chronological order.
|
||||
* <p>Command classes are never persisted.
|
||||
* Whenever a command that mutates the model is executed, a {@link
|
||||
* google.registry.reporting.HistoryEvent} is stored with the affected Resource as an embedded
|
||||
* field. All history entries have an indexed modification time field so that the history can be
|
||||
* read in chronological order.
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,6 @@ import google.registry.model.ImmutableObject;
|
|||
import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.registrar.RegistrarPoc.RegistrarPocId;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.io.Serializable;
|
||||
|
@ -57,7 +56,6 @@ import javax.persistence.Table;
|
|||
* *MUST* also modify the persisted Registrar entity with {@link Registrar#contactsRequireSyncing}
|
||||
* set to true.
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "gaeUserId", name = "registrarpoc_gae_user_id_idx")})
|
||||
@IdClass(RegistrarPocId.class)
|
||||
|
|
|
@ -23,8 +23,6 @@ import com.google.common.base.Splitter;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.hash.BloomFilter;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.label.PremiumList.PremiumEntry;
|
||||
import java.io.Serializable;
|
||||
|
@ -35,6 +33,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
@ -49,8 +48,7 @@ import org.joda.money.Money;
|
|||
* succeeds, we will end up with having two exact same premium lists that differ only by revisionId.
|
||||
* This is fine though, because we only use the list with the highest revisionId.
|
||||
*/
|
||||
@ReportedOn
|
||||
@javax.persistence.Entity
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "name", name = "premiumlist_name_idx")})
|
||||
public final class PremiumList extends BaseDomainLabelList<BigDecimal, PremiumEntry> {
|
||||
|
||||
|
@ -64,7 +62,7 @@ public final class PremiumList extends BaseDomainLabelList<BigDecimal, PremiumEn
|
|||
* from the immutability contract so we can modify it after construction and we have to handle the
|
||||
* database processing on our own so we can detach it after load.
|
||||
*/
|
||||
@ImmutableObject.Insignificant @Transient ImmutableMap<String, BigDecimal> labelsToPrices;
|
||||
@Insignificant @Transient ImmutableMap<String, BigDecimal> labelsToPrices;
|
||||
|
||||
@Column(nullable = false)
|
||||
BloomFilter<String> bloomFilter;
|
||||
|
@ -116,11 +114,11 @@ public final class PremiumList extends BaseDomainLabelList<BigDecimal, PremiumEn
|
|||
* A premium list entry entity, persisted to Cloud SQL. Each instance represents the price of a
|
||||
* single label on a given TLD.
|
||||
*/
|
||||
@javax.persistence.Entity(name = "PremiumEntry")
|
||||
@Entity(name = "PremiumEntry")
|
||||
public static class PremiumEntry extends DomainLabelEntry<BigDecimal, PremiumList.PremiumEntry>
|
||||
implements Buildable, Serializable {
|
||||
|
||||
@ImmutableObject.Insignificant @javax.persistence.Id Long revisionId;
|
||||
@Insignificant @javax.persistence.Id Long revisionId;
|
||||
|
||||
@Column(nullable = false)
|
||||
BigDecimal price;
|
||||
|
|
|
@ -29,11 +29,7 @@ import org.joda.time.DateTime;
|
|||
@XmlTransient
|
||||
@MappedSuperclass
|
||||
public abstract class BaseTransferObject extends ImmutableObject implements UnsafeSerializable {
|
||||
/**
|
||||
* The status of the current or last transfer. Can be null if never transferred. Note that we
|
||||
* leave IgnoreSave off this field so that we can ensure that TransferData loaded from Objectify
|
||||
* will always be non-null.
|
||||
*/
|
||||
/** The status of the current or last transfer. Can be null if never transferred. */
|
||||
@XmlElement(name = "trStatus")
|
||||
@Enumerated(EnumType.STRING)
|
||||
TransferStatus transferStatus;
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import com.googlecode.objectify.impl.Path;
|
||||
import com.googlecode.objectify.impl.Property;
|
||||
import com.googlecode.objectify.impl.translate.CreateContext;
|
||||
import com.googlecode.objectify.impl.translate.LoadContext;
|
||||
import com.googlecode.objectify.impl.translate.SaveContext;
|
||||
import com.googlecode.objectify.impl.translate.ValueTranslator;
|
||||
import com.googlecode.objectify.impl.translate.ValueTranslatorFactory;
|
||||
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/** Common boilerplate for translator factories. */
|
||||
public abstract class AbstractSimpleTranslatorFactory<P, D> extends ValueTranslatorFactory<P, D> {
|
||||
|
||||
public AbstractSimpleTranslatorFactory(Class<P> clazz) {
|
||||
super(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final ValueTranslator<P, D> createSafe(
|
||||
Path path, Property property, Type type, CreateContext ctx) {
|
||||
return new ValueTranslator<P, D>(path, new TypeInstantiator<D>(getClass()){}.getExactType()) {
|
||||
|
||||
SimpleTranslator<P, D> simpleTranslator = createTranslator();
|
||||
|
||||
@Override
|
||||
protected P loadValue(D datastoreValue, LoadContext ctx) {
|
||||
return simpleTranslator.loadValue(datastoreValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected D saveValue(P pojoValue, SaveContext ctx) {
|
||||
return simpleTranslator.saveValue(pojoValue);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Translator with reduced boilerplate. */
|
||||
interface SimpleTranslator<P, D> {
|
||||
P loadValue(D datastoreValue);
|
||||
|
||||
D saveValue(P pojoValue);
|
||||
}
|
||||
|
||||
abstract SimpleTranslator<P, D> createTranslator();
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import static com.google.common.hash.Funnels.unencodedCharsFunnel;
|
||||
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.erase;
|
||||
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.getTypeParameter;
|
||||
|
||||
import com.google.appengine.api.datastore.Blob;
|
||||
import com.google.common.hash.BloomFilter;
|
||||
import com.google.common.hash.Funnel;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.googlecode.objectify.impl.Path;
|
||||
import com.googlecode.objectify.impl.Property;
|
||||
import com.googlecode.objectify.impl.translate.CreateContext;
|
||||
import com.googlecode.objectify.impl.translate.LoadContext;
|
||||
import com.googlecode.objectify.impl.translate.SaveContext;
|
||||
import com.googlecode.objectify.impl.translate.Translator;
|
||||
import com.googlecode.objectify.impl.translate.TranslatorFactory;
|
||||
import com.googlecode.objectify.impl.translate.ValueTranslator;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Stores CharSequence {@link BloomFilter}s as blobs. */
|
||||
public class BloomFilterOfStringTranslatorFactory
|
||||
implements TranslatorFactory<BloomFilter<String>> {
|
||||
|
||||
@Override
|
||||
public Translator<BloomFilter<String>> create(
|
||||
Path path, Property property, Type type, CreateContext ctx) {
|
||||
if (!BloomFilter.class.equals(erase(type))) {
|
||||
return null; // Skip me and try to find another matching translator
|
||||
}
|
||||
Type fieldBloomFilterType = getTypeParameter(type, BloomFilter.class.getTypeParameters()[0]);
|
||||
if (fieldBloomFilterType == null) {
|
||||
return null; // No type information is available
|
||||
}
|
||||
if (!TypeToken.of(String.class).getType().equals(fieldBloomFilterType)) {
|
||||
return null; // We can only handle BloomFilters of CharSequences
|
||||
}
|
||||
|
||||
return new ValueTranslator<BloomFilter<String>, Blob>(path, Blob.class) {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected BloomFilter<String> loadValue(Blob value, LoadContext ctx) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Funnel<String> castedFunnel = (Funnel<String>) (Funnel<?>) unencodedCharsFunnel();
|
||||
return BloomFilter.readFrom(new ByteArrayInputStream(value.getBytes()), castedFunnel);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Error loading Bloom filter data", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Blob saveValue(BloomFilter<String> value, SaveContext ctx) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try {
|
||||
value.writeTo(bos);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Error saving Bloom filter data", e);
|
||||
}
|
||||
return new Blob(bos.toByteArray());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
|
||||
/** Stores {@link CidrAddressBlock} as a canonicalized string. */
|
||||
public class CidrAddressBlockTranslatorFactory
|
||||
extends AbstractSimpleTranslatorFactory<CidrAddressBlock, String> {
|
||||
|
||||
public CidrAddressBlockTranslatorFactory() {
|
||||
super(CidrAddressBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleTranslator<CidrAddressBlock, String> createTranslator() {
|
||||
return new SimpleTranslator<CidrAddressBlock, String>(){
|
||||
@Override
|
||||
public CidrAddressBlock loadValue(String datastoreValue) {
|
||||
return CidrAddressBlock.create(datastoreValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveValue(CidrAddressBlock pojoValue) {
|
||||
return pojoValue.toString();
|
||||
}};
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import org.joda.money.CurrencyUnit;
|
||||
|
||||
/** Stores {@link CurrencyUnit} as a canonicalized string. */
|
||||
public class CurrencyUnitTranslatorFactory
|
||||
extends AbstractSimpleTranslatorFactory<CurrencyUnit, String> {
|
||||
|
||||
public CurrencyUnitTranslatorFactory() {
|
||||
super(CurrencyUnit.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleTranslator<CurrencyUnit, String> createTranslator() {
|
||||
return new SimpleTranslator<CurrencyUnit, String>(){
|
||||
@Override
|
||||
public CurrencyUnit loadValue(String datastoreValue) {
|
||||
return CurrencyUnit.of(datastoreValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveValue(CurrencyUnit pojoValue) {
|
||||
return pojoValue.toString();
|
||||
}};
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Stores {@link Duration} as a canonicalized string. */
|
||||
public class DurationTranslatorFactory extends AbstractSimpleTranslatorFactory<Duration, String> {
|
||||
|
||||
public DurationTranslatorFactory() {
|
||||
super(Duration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SimpleTranslator<Duration, String> createTranslator() {
|
||||
return new SimpleTranslator<Duration, String>() {
|
||||
@Override
|
||||
public Duration loadValue(String datastoreValue) {
|
||||
return Duration.parse(datastoreValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveValue(Duration pojoValue) {
|
||||
return pojoValue.toString();
|
||||
}};
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.erase;
|
||||
import static com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector.getTypeParameter;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.googlecode.objectify.impl.Node;
|
||||
import com.googlecode.objectify.impl.Path;
|
||||
import com.googlecode.objectify.impl.Property;
|
||||
import com.googlecode.objectify.impl.translate.CreateContext;
|
||||
import com.googlecode.objectify.impl.translate.ListNodeTranslator;
|
||||
import com.googlecode.objectify.impl.translate.LoadContext;
|
||||
import com.googlecode.objectify.impl.translate.SaveContext;
|
||||
import com.googlecode.objectify.impl.translate.SkipException;
|
||||
import com.googlecode.objectify.impl.translate.Translator;
|
||||
import com.googlecode.objectify.impl.translate.TranslatorFactory;
|
||||
import com.googlecode.objectify.impl.translate.TranslatorRegistry;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Abstract Objectify translator for {@link ImmutableSortedMap} fields.
|
||||
*
|
||||
* <p>This class should be extended for each set of concrete key/value types you wish to support.
|
||||
* This translator will only apply to {@code ImmutableSortedMap} model fields that have precicely
|
||||
* the same type parameters you specified.
|
||||
*
|
||||
* <p>This translator serves a similar purpose to
|
||||
* {@link com.googlecode.objectify.impl.translate.MapifyTranslatorFactory @Mapify}. Except this
|
||||
* maintains perfect immutability of the field value. Subclasses may override the
|
||||
* {@link #transformBeforeSave(ImmutableSortedMap)} methods to perform mutation on a per-concrete
|
||||
* type basis. This abstraction is also more readable than {@code @Mapify} because it shifts the
|
||||
* boilerplate into translator magic, rather than convoluting model data structures.
|
||||
*
|
||||
* <h3>Entity Data Layout</h3>
|
||||
*
|
||||
* <p>For example, if you had an {@code ImmutableSortedMap<String, String>} on a field named
|
||||
* {@code field}, then this would look like:<pre> {@code
|
||||
*
|
||||
* field.key: key1 -> key2
|
||||
* field.value: value1 -> value2}</pre>
|
||||
*
|
||||
* <p>If you had an {@code ImmutableSortedMap<String, EmbeddedClass>} on a field named
|
||||
* {@code field}, where {@code EmbeddedClass} defines two {@code foo} and {@code bar} fields, then
|
||||
* the embedded properties might look like:<pre> {@code
|
||||
*
|
||||
* field.key: key1 -> key2
|
||||
* field.value.foo: foo1 -> foo2
|
||||
* field.value.bar: bar1 -> bar2}</pre>
|
||||
*
|
||||
* @param <K> key type for sorted map which must be {@link Comparable}
|
||||
* @param <V> value type for sorted map
|
||||
*/
|
||||
abstract class ImmutableSortedMapTranslatorFactory<K extends Comparable<? super K>, V>
|
||||
implements TranslatorFactory<ImmutableSortedMap<K, V>> {
|
||||
|
||||
private final TypeToken<K> keyType = new TypeToken<K>(getClass()) {};
|
||||
private final TypeToken<V> valueType = new TypeToken<V>(getClass()) {};
|
||||
private final String keyProperty;
|
||||
private final String valueProperty;
|
||||
|
||||
ImmutableSortedMapTranslatorFactory() {
|
||||
this("key", "value");
|
||||
}
|
||||
|
||||
/** Constructs a instance that's compatible with models migrated from {@code @Mapify}. */
|
||||
ImmutableSortedMapTranslatorFactory(String keyProperty, String valueProperty) {
|
||||
this.keyProperty = checkNotNull(keyProperty);
|
||||
this.valueProperty = checkNotNull(valueProperty);
|
||||
}
|
||||
|
||||
/** Allows for changing the field data structure before it's written to the raw entity object. */
|
||||
ImmutableSortedMap<K, V> transformBeforeSave(ImmutableSortedMap<K, V> map) {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Translator<ImmutableSortedMap<K, V>>
|
||||
create(Path path, Property property, Type type, CreateContext ctx) {
|
||||
if (!ImmutableSortedMap.class.equals(erase(type))) {
|
||||
return null; // skip me and try to find another matching translator
|
||||
}
|
||||
Type fieldKeyType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[0]);
|
||||
Type fieldValueType = getTypeParameter(type, ImmutableSortedMap.class.getTypeParameters()[1]);
|
||||
if (fieldKeyType == null || fieldValueType == null) {
|
||||
return null; // no type information is available
|
||||
}
|
||||
if (!keyType.isSupertypeOf(fieldKeyType) || !valueType.isSupertypeOf(fieldValueType)) {
|
||||
return null; // this ImmutableSortedMap does not have the same concrete component types
|
||||
}
|
||||
ctx.enterCollection(path);
|
||||
ctx.enterEmbed(path);
|
||||
try {
|
||||
// The component types can also be translated by Objectify!
|
||||
TranslatorRegistry translators = ctx.getFactory().getTranslators();
|
||||
final Translator<K> keyTranslator =
|
||||
translators.create(path.extend(keyProperty), property, fieldKeyType, ctx);
|
||||
final Translator<V> valueTranslator =
|
||||
translators.create(path.extend(valueProperty), property, fieldValueType, ctx);
|
||||
return new ListNodeTranslator<ImmutableSortedMap<K, V>>() {
|
||||
@Override
|
||||
protected ImmutableSortedMap<K, V> loadList(Node node, LoadContext ctx) {
|
||||
ImmutableSortedMap.Builder<K, V> map =
|
||||
new ImmutableSortedMap.Builder<>(Ordering.natural());
|
||||
for (Node child : node) {
|
||||
try {
|
||||
map.put(keyTranslator.load(child.get(keyProperty), ctx),
|
||||
valueTranslator.load(child.get(valueProperty), ctx));
|
||||
} catch (SkipException e) {
|
||||
// no problem, just skip that one
|
||||
}
|
||||
}
|
||||
return map.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node saveList(
|
||||
@Nullable ImmutableSortedMap<K, V> mapFromPojo,
|
||||
Path path,
|
||||
boolean index,
|
||||
SaveContext ctx) {
|
||||
checkState(!index, "At path %s: Index not allowed", path);
|
||||
ImmutableSortedMap<K, V> mapToSave = transformBeforeSave(
|
||||
ImmutableSortedMap.copyOfSorted(nullToEmpty(mapFromPojo)));
|
||||
if (mapToSave.isEmpty()) {
|
||||
throw new SkipException(); // Datastore doesn't store empty lists
|
||||
}
|
||||
Node node = new Node(path);
|
||||
for (Map.Entry<K, V> entry : mapToSave.entrySet()) {
|
||||
Node item = new Node(path);
|
||||
item.put(keyProperty,
|
||||
keyTranslator.save(entry.getKey(), path.extend(keyProperty), index, ctx));
|
||||
item.put(valueProperty,
|
||||
valueTranslator.save(entry.getValue(), path.extend(valueProperty), index, ctx));
|
||||
node.addToList(item);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
ctx.exitEmbed();
|
||||
ctx.exitCollection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import com.google.common.net.InetAddresses;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/** Stores {@link InetAddress} as a canonicalized string. */
|
||||
public class InetAddressTranslatorFactory
|
||||
extends AbstractSimpleTranslatorFactory<InetAddress, String> {
|
||||
|
||||
public InetAddressTranslatorFactory() {
|
||||
super(InetAddress.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleTranslator<InetAddress, String> createTranslator() {
|
||||
return new SimpleTranslator<InetAddress, String>() {
|
||||
@Override
|
||||
public InetAddress loadValue(String datastoreValue) {
|
||||
return InetAddresses.forString(datastoreValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveValue(InetAddress pojoValue) {
|
||||
return pojoValue.getHostAddress();
|
||||
}};
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2017 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.model.translators;
|
||||
|
||||
import com.googlecode.objectify.impl.Path;
|
||||
import com.googlecode.objectify.impl.Property;
|
||||
import com.googlecode.objectify.impl.TypeUtils;
|
||||
import com.googlecode.objectify.impl.translate.CreateContext;
|
||||
import com.googlecode.objectify.impl.translate.LoadContext;
|
||||
import com.googlecode.objectify.impl.translate.SaveContext;
|
||||
import com.googlecode.objectify.impl.translate.ValueTranslator;
|
||||
import com.googlecode.objectify.impl.translate.ValueTranslatorFactory;
|
||||
import com.googlecode.objectify.repackaged.gentyref.GenericTypeReflector;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
/**
|
||||
* Stores Joda {@link ReadableInstant} types ({@code DateTime}, etc) as a {@link java.util.Date}.
|
||||
*
|
||||
* <p>This is a fork of the {@code ReadableInstantTranslatorFactory} that comes bundled with
|
||||
* Objectify. The original reifies a {@link ReadableInstant} using the machine's local time
|
||||
* zone. This version always uses UTC.
|
||||
*/
|
||||
public class ReadableInstantUtcTranslatorFactory
|
||||
extends ValueTranslatorFactory<ReadableInstant, Date> {
|
||||
|
||||
public ReadableInstantUtcTranslatorFactory() {
|
||||
super(ReadableInstant.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValueTranslator<ReadableInstant, Date> createSafe(
|
||||
Path path, Property property, Type type, CreateContext ctx) {
|
||||
final Class<?> clazz = GenericTypeReflector.erase(type);
|
||||
|
||||
return new ValueTranslator<ReadableInstant, Date>(path, Date.class) {
|
||||
@Override
|
||||
protected ReadableInstant loadValue(Date value, LoadContext ctx) {
|
||||
// All the Joda instants have a constructor that will take a Date and timezone.
|
||||
Constructor<?> ctor = TypeUtils.getConstructor(clazz, Object.class, DateTimeZone.class);
|
||||
return (ReadableInstant) TypeUtils.newInstance(ctor, value, DateTimeZone.UTC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Date saveValue(ReadableInstant value, SaveContext ctx) {
|
||||
return value.toInstant().toDate();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ import javax.annotation.Nullable;
|
|||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
|
||||
/**
|
||||
* Creates queries that can be used both for objectify and JPA.
|
||||
* Creates queries that can be used JPA.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
|
|
@ -53,8 +53,8 @@ import javax.inject.Inject;
|
|||
* <p>All commands and responses conform to the RDAP spec as defined in RFCs 7480 through 7485.
|
||||
*
|
||||
* <p>The RDAP specification lumps contacts and registrars together and calls them "entities", which
|
||||
* is confusing for us, because "entity" means something else in Objectify. But here, when we use
|
||||
* the term, it means either a contact or registrar. When searching for entities, we always start by
|
||||
* is confusing for us, because "entity" means something else in SQL. But here, when we use the
|
||||
* term, it means either a contact or registrar. When searching for entities, we always start by
|
||||
* returning all matching contacts, and after that all matching registrars.
|
||||
*
|
||||
* <p>There are two ways to search for entities: by full name (for contacts, the search name, for
|
||||
|
|
|
@ -18,7 +18,6 @@ import static com.google.common.base.Verify.verify;
|
|||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
|
@ -164,10 +163,12 @@ public final class RdeMarshaller implements Serializable {
|
|||
try {
|
||||
xml = marshal(element);
|
||||
} catch (MarshalException e) {
|
||||
error = String.format("RDE XML schema validation failed: %s\n%s%s\n",
|
||||
Key.create(resource),
|
||||
e.getLinkedException(),
|
||||
getMarshaller().marshalLenient(element));
|
||||
error =
|
||||
String.format(
|
||||
"RDE XML schema validation failed: %s\n%s%s\n",
|
||||
resource.createVKey(),
|
||||
e.getLinkedException(),
|
||||
getMarshaller().marshalLenient(element));
|
||||
logger.atSevere().withCause(e).log(error);
|
||||
}
|
||||
return DepositFragment.create(type, xml, error);
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
|
@ -33,7 +34,6 @@ import google.registry.model.domain.GracePeriod;
|
|||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
|
|
@ -21,7 +21,7 @@ import google.registry.testing.FakeClock;
|
|||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Base class of all unit tests for entities which are persisted to Datastore via Objectify. */
|
||||
/** Base class of all unit tests for entities which are persisted to SQL. */
|
||||
public abstract class EntityTestCase {
|
||||
|
||||
protected enum JpaEntityCoverageCheck {
|
||||
|
|
|
@ -17,7 +17,6 @@ package google.registry.model;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
@ -34,14 +33,13 @@ public class ModelUtilsTest {
|
|||
/** Test class for reflection methods. */
|
||||
public static class TestClass extends ImmutableObject implements Buildable {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
String a;
|
||||
|
||||
String b;
|
||||
|
||||
/** Note that there is no getter for {@link #b}.*/
|
||||
/** Note that there is no getter for {@link #b}. */
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -50,7 +48,7 @@ public class ModelUtilsTest {
|
|||
return a;
|
||||
}
|
||||
|
||||
/** Builder for {@link TestClass}. Note that there is no setter for {@link #a}.*/
|
||||
/** Builder for {@link TestClass}. Note that there is no setter for {@link #a}. */
|
||||
public static class Builder extends Buildable.Builder<TestClass> {
|
||||
|
||||
protected Builder() {}
|
||||
|
@ -83,10 +81,11 @@ public class ModelUtilsTest {
|
|||
|
||||
@Test
|
||||
void testGetAllFields() throws Exception {
|
||||
Map<String, Field> expected = ImmutableMap.of(
|
||||
"id", TestClass.class.getDeclaredField("id"),
|
||||
"a", TestClass.class.getDeclaredField("a"),
|
||||
"b", TestClass.class.getDeclaredField("b"));
|
||||
Map<String, Field> expected =
|
||||
ImmutableMap.of(
|
||||
"id", TestClass.class.getDeclaredField("id"),
|
||||
"a", TestClass.class.getDeclaredField("a"),
|
||||
"b", TestClass.class.getDeclaredField("b"));
|
||||
// More complicated version of isEqualTo() so that we check for ordering.
|
||||
assertThat(ModelUtils.getAllFields(TestClass.class).entrySet())
|
||||
.containsExactlyElementsIn(expected.entrySet())
|
||||
|
@ -127,7 +126,7 @@ public class ModelUtilsTest {
|
|||
original.id = "foo";
|
||||
TestClass cloned = original.asBuilder().setId("bar").build();
|
||||
assertThat(cloned.hashCode()).isNotEqualTo(original.hashCode());
|
||||
cloned.id = "foo"; // Violates immutability contract.
|
||||
cloned.id = "foo"; // Violates immutability contract.
|
||||
// The hashCode is now cached and is stale (but that's the expected behavior).
|
||||
assertThat(cloned.hashCode()).isNotEqualTo(original.hashCode());
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.translators;
|
||||
package google.registry.model.adapters;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
|
@ -888,9 +888,7 @@ public class DomainTest {
|
|||
|
||||
@Test
|
||||
void testHistoryIdRestoration() {
|
||||
// Verify that history ids for billing events are restored during load from datastore. History
|
||||
// ids are not used by business code or persisted in datastore, but only to reconstruct
|
||||
// objectify keys when loading from SQL.
|
||||
// Verify that history ids for billing events are restored during load.
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
domain =
|
||||
persistResource(
|
||||
|
|
|
@ -20,15 +20,14 @@ import static google.registry.persistence.transaction.QueryComposer.Comparator;
|
|||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -44,13 +43,11 @@ public class QueryComposerTest {
|
|||
TestEntity charlie = new TestEntity("charlie", 1);
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
public final JpaUnitTestExtension jpa =
|
||||
new JpaTestExtensions.Builder()
|
||||
.withClock(fakeClock)
|
||||
.withCloudSql()
|
||||
.withOfyTestEntities(TestEntity.class)
|
||||
.withJpaUnitTestEntities(TestEntity.class)
|
||||
.build();
|
||||
.withEntityClass(TestEntity.class)
|
||||
.buildUnitTestExtension();
|
||||
|
||||
public QueryComposerTest() {}
|
||||
|
||||
|
@ -319,12 +316,10 @@ public class QueryComposerTest {
|
|||
.isEmpty();
|
||||
}
|
||||
|
||||
@javax.persistence.Entity
|
||||
@Entity(name = "QueryComposerTestEntity")
|
||||
@Entity
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
@javax.persistence.Id @Id private String name;
|
||||
@Id private String name;
|
||||
|
||||
@Index
|
||||
// Renaming this implicitly verifies that property names work for hibernate queries.
|
||||
@Column(name = "some_value")
|
||||
private int val;
|
||||
|
|
|
@ -1125,7 +1125,7 @@ public final class DatabaseHelper {
|
|||
.build());
|
||||
}
|
||||
|
||||
/** Persists a single Objectify resource, without adjusting foreign resources or keys. */
|
||||
/** Persists a single resource, without adjusting foreign resources or keys. */
|
||||
public static <R> R persistSimpleResource(final R resource) {
|
||||
return persistSimpleResources(ImmutableList.of(resource)).get(0);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public final class DiffUtils {
|
|||
&& aValue == null
|
||||
&& bValue instanceof Collection
|
||||
&& ((Collection<?>) bValue).isEmpty()) {
|
||||
// Ignore a mismatch between Objectify's use of null to store empty collections and our
|
||||
// Ignore a mismatch between the use of null to store empty collections and our
|
||||
// code's builder methods, which yield empty collections for the same fields. This
|
||||
// prevents useless lines of the form "[null, []]" from appearing in diffs.
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue