The only remaining Ofy entity is GaeUserConverter after this PR. (#1838)

Therefore this PR also removed several classes and related tests that
support the setup and verification of Ofy entities.

In addition, support for creating a VKey from a string is limited to
VKey<? extends EppResource> only because it is the only use case (to
pass a key to an EPP resource in a web safe way to facilitate resave),
and we do not want to keep an extra simple name to class mapping, in
addition to what persistence.xml contains. I looked into using
PersistenceXmlUtility to obtain the mapping, but the xml file contains
classes with the same simple name (namely OneTime from both PollMessage
and BillingEvent). It doesn't seem like a worthwhile investment to write
more code to deal with that, when the fact is that we only need to
consider EppResource.
This commit is contained in:
Lai Jiang 2022-11-04 12:47:11 -04:00 committed by GitHub
parent 558bfd1ca2
commit 536f82eb9a
105 changed files with 469 additions and 1618 deletions

View file

@ -65,7 +65,7 @@ public final class AsyncTaskEnqueuer {
private final Queue asyncDnsRefreshPullQueue; private final Queue asyncDnsRefreshPullQueue;
private final Retrier retrier; private final Retrier retrier;
private CloudTasksUtils cloudTasksUtils; private final CloudTasksUtils cloudTasksUtils;
@Inject @Inject
public AsyncTaskEnqueuer( public AsyncTaskEnqueuer(
@ -82,7 +82,8 @@ public final class AsyncTaskEnqueuer {
} }
/** Enqueues a task to asynchronously re-save an entity at some point in the future. */ /** Enqueues a task to asynchronously re-save an entity at some point in the future. */
public void enqueueAsyncResave(VKey<?> entityToResave, DateTime now, DateTime whenToResave) { public void enqueueAsyncResave(
VKey<? extends EppResource> entityToResave, DateTime now, DateTime whenToResave) {
enqueueAsyncResave(entityToResave, now, ImmutableSortedSet.of(whenToResave)); enqueueAsyncResave(entityToResave, now, ImmutableSortedSet.of(whenToResave));
} }
@ -93,7 +94,9 @@ public final class AsyncTaskEnqueuer {
* itself to run at the next time if there are remaining re-saves scheduled. * itself to run at the next time if there are remaining re-saves scheduled.
*/ */
public void enqueueAsyncResave( public void enqueueAsyncResave(
VKey<?> entityKey, DateTime now, ImmutableSortedSet<DateTime> whenToResave) { VKey<? extends EppResource> entityKey,
DateTime now,
ImmutableSortedSet<DateTime> whenToResave) {
DateTime firstResave = whenToResave.first(); DateTime firstResave = whenToResave.first();
checkArgument(isBeforeOrAt(now, firstResave), "Can't enqueue a resave to run in the past"); checkArgument(isBeforeOrAt(now, firstResave), "Can't enqueue a resave to run in the past");
Duration etaDuration = new Duration(now, firstResave); Duration etaDuration = new Duration(now, firstResave);

View file

@ -52,7 +52,7 @@ public class CheckPackagesComplianceAction implements Runnable {
"FROM DomainHistory WHERE current_package_token = :token AND" "FROM DomainHistory WHERE current_package_token = :token AND"
+ " modificationTime >= :lastBilling AND type = 'DOMAIN_CREATE'", + " modificationTime >= :lastBilling AND type = 'DOMAIN_CREATE'",
DomainHistory.class) DomainHistory.class)
.setParameter("token", packagePromo.getToken().getSqlKey().toString()) .setParameter("token", packagePromo.getToken().getKey().toString())
.setParameter( .setParameter(
"lastBilling", packagePromo.getNextBillingDate().minusYears(1)) "lastBilling", packagePromo.getNextBillingDate().minusYears(1))
.getResultList(); .getResultList();
@ -62,7 +62,7 @@ public class CheckPackagesComplianceAction implements Runnable {
logger.atInfo().log( logger.atInfo().log(
"Package with package token %s has exceeded their max domain creation limit" "Package with package token %s has exceeded their max domain creation limit"
+ " by %d name(s).", + " by %d name(s).",
packagePromo.getToken().getSqlKey(), overage); packagePromo.getToken().getKey(), overage);
packagesOverCreateLimit.add(packagePromo); packagesOverCreateLimit.add(packagePromo);
} }
} }

View file

@ -253,7 +253,7 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
final ImmutableSet<DateTime> billingTimes = final ImmutableSet<DateTime> billingTimes =
getBillingTimesInScope(eventTimes, cursorTime, executeTime, tld); getBillingTimesInScope(eventTimes, cursorTime, executeTime, tld);
VKey<Domain> domainKey = VKey.createSql(Domain.class, recurring.getDomainRepoId()); VKey<Domain> domainKey = VKey.create(Domain.class, recurring.getDomainRepoId());
Iterable<OneTime> oneTimesForDomain; Iterable<OneTime> oneTimesForDomain;
oneTimesForDomain = oneTimesForDomain =
tm().createQueryComposer(OneTime.class) tm().createQueryComposer(OneTime.class)

View file

@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.Action.Method; import google.registry.request.Action.Method;
@ -75,14 +74,11 @@ public class ResaveEntityAction implements Runnable {
"Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime); "Re-saving entity %s which was enqueued at %s.", resourceKey, requestedTime);
tm().transact( tm().transact(
() -> { () -> {
ImmutableObject entity = tm().loadByKey(VKey.create(resourceKey)); EppResource entity = tm().loadByKey(VKey.createEppVKeyFromString(resourceKey));
tm().put( tm().put(entity.cloneProjectedAtTime(tm().getTransactionTime()));
(entity instanceof EppResource)
? ((EppResource) entity).cloneProjectedAtTime(tm().getTransactionTime())
: entity);
if (!resaveTimes.isEmpty()) { if (!resaveTimes.isEmpty()) {
asyncTaskEnqueuer.enqueueAsyncResave( asyncTaskEnqueuer.enqueueAsyncResave(
VKey.create(resourceKey), requestedTime, resaveTimes); VKey.createEppVKeyFromString(resourceKey), requestedTime, resaveTimes);
} }
}); });
response.setPayload("Entity re-saved."); response.setPayload("Entity re-saved.");

View file

@ -303,7 +303,7 @@ public class RdePipeline implements Serializable {
TypeDescriptor.of(DepositFragment.class))) TypeDescriptor.of(DepositFragment.class)))
.via( .via(
(String registrarRepoId) -> { (String registrarRepoId) -> {
VKey<Registrar> key = VKey.createSql(Registrar.class, registrarRepoId); VKey<Registrar> key = VKey.create(Registrar.class, registrarRepoId);
includedRegistrarCounter.inc(); includedRegistrarCounter.inc();
Registrar registrar = jpaTm().transact(() -> jpaTm().loadByKey(key)); Registrar registrar = jpaTm().transact(() -> jpaTm().loadByKey(key));
DepositFragment fragment = marshaller.marshalRegistrar(registrar); DepositFragment fragment = marshaller.marshalRegistrar(registrar);
@ -332,9 +332,9 @@ public class RdePipeline implements Serializable {
("SELECT repoId, revisionId FROM %entity% WHERE (repoId, modificationTime) IN" ("SELECT repoId, revisionId FROM %entity% WHERE (repoId, modificationTime) IN"
+ " (SELECT repoId, MAX(modificationTime) FROM %entity% WHERE" + " (SELECT repoId, MAX(modificationTime) FROM %entity% WHERE"
+ " modificationTime <= :watermark GROUP BY repoId) AND resource.deletionTime" + " modificationTime <= :watermark GROUP BY repoId) AND resource.deletionTime"
+ " > :watermark AND COALESCE(resource.creationClientId, '') NOT LIKE" + " > :watermark AND COALESCE(resource.creationRegistrarId, '') NOT LIKE"
+ " 'prober-%' AND COALESCE(resource.currentSponsorClientId, '') NOT LIKE" + " 'prober-%' AND COALESCE(resource.currentSponsorRegistrarId, '') NOT LIKE"
+ " 'prober-%' AND COALESCE(resource.lastEppUpdateClientId, '') NOT LIKE" + " 'prober-%' AND COALESCE(resource.lastEppUpdateRegistrarId, '') NOT LIKE"
+ " 'prober-%' " + " 'prober-%' "
+ (historyClass == DomainHistory.class + (historyClass == DomainHistory.class
? "AND resource.tld IN " + "(SELECT id FROM Tld WHERE tldType = 'REAL')" ? "AND resource.tld IN " + "(SELECT id FROM Tld WHERE tldType = 'REAL')"
@ -381,7 +381,7 @@ public class RdePipeline implements Serializable {
() -> () ->
jpaTm() jpaTm()
.loadByKey( .loadByKey(
VKey.createSql(historyEntryClazz, new HistoryEntryId(repoId, revisionId)))) VKey.create(historyEntryClazz, new HistoryEntryId(repoId, revisionId))))
.getResourceAtPointInTime() .getResourceAtPointInTime()
.map(resource -> resource.cloneProjectedAtTime(watermark)) .map(resource -> resource.cloneProjectedAtTime(watermark))
.get(); .get();
@ -469,12 +469,12 @@ public class RdePipeline implements Serializable {
// Contacts and hosts are only deposited in RDE, not BRDA. // Contacts and hosts are only deposited in RDE, not BRDA.
if (pendingDeposit.mode() == RdeMode.FULL) { if (pendingDeposit.mode() == RdeMode.FULL) {
HashSet<Serializable> contacts = new HashSet<>(); HashSet<Serializable> contacts = new HashSet<>();
contacts.add(domain.getAdminContact().getSqlKey()); contacts.add(domain.getAdminContact().getKey());
contacts.add(domain.getTechContact().getSqlKey()); contacts.add(domain.getTechContact().getKey());
contacts.add(domain.getRegistrant().getSqlKey()); contacts.add(domain.getRegistrant().getKey());
// Billing contact is not mandatory. // Billing contact is not mandatory.
if (domain.getBillingContact() != null) { if (domain.getBillingContact() != null) {
contacts.add(domain.getBillingContact().getSqlKey()); contacts.add(domain.getBillingContact().getKey());
} }
referencedContactCounter.inc(contacts.size()); referencedContactCounter.inc(contacts.size());
contacts.forEach( contacts.forEach(
@ -492,7 +492,7 @@ public class RdePipeline implements Serializable {
.get(REFERENCED_HOSTS) .get(REFERENCED_HOSTS)
.output( .output(
KV.of( KV.of(
(String) hostKey.getSqlKey(), (String) hostKey.getKey(),
pendingDeposit))); pendingDeposit)));
} }
} }
@ -565,7 +565,7 @@ public class RdePipeline implements Serializable {
// The output are pairs of // The output are pairs of
// (superordinateDomainRepoId, // (superordinateDomainRepoId,
// (subordinateHostRepoId, (pendingDeposit, revisionId))). // (subordinateHostRepoId, (pendingDeposit, revisionId))).
KV.of((String) host.getSuperordinateDomain().getSqlKey(), kv)); KV.of((String) host.getSuperordinateDomain().getKey(), kv));
} else { } else {
externalHostCounter.inc(); externalHostCounter.inc();
DepositFragment fragment = marshaller.marshalExternalHost(host); DepositFragment fragment = marshaller.marshalExternalHost(host);

View file

@ -115,7 +115,7 @@ public class Spec11Pipeline implements Serializable {
Read<Object[], KV<String, String>> read = Read<Object[], KV<String, String>> read =
RegistryJpaIO.read( RegistryJpaIO.read(
"select d.repoId, r.emailAddress from Domain d join Registrar r on" "select d.repoId, r.emailAddress from Domain d join Registrar r on"
+ " d.currentSponsorClientId = r.registrarId where r.type = 'REAL' and" + " d.currentSponsorRegistrarId = r.registrarId where r.type = 'REAL' and"
+ " d.deletionTime > now()", + " d.deletionTime > now()",
false, false,
Spec11Pipeline::parseRow) Spec11Pipeline::parseRow)
@ -133,9 +133,7 @@ public class Spec11Pipeline implements Serializable {
Domain domain = Domain domain =
jpaTm() jpaTm()
.transact( .transact(
() -> () -> jpaTm().loadByKey(VKey.create(Domain.class, input.getKey())));
jpaTm()
.loadByKey(VKey.createSql(Domain.class, input.getKey())));
String emailAddress = input.getValue(); String emailAddress = input.getValue();
if (emailAddress == null) { if (emailAddress == null) {
emailAddress = ""; emailAddress = "";

View file

@ -163,7 +163,7 @@ public final class ResourceFlowUtils {
// The roid should match one of the contacts. // The roid should match one of the contacts.
Optional<VKey<Contact>> foundContact = Optional<VKey<Contact>> foundContact =
domain.getReferencedContacts().stream() domain.getReferencedContacts().stream()
.filter(key -> key.getSqlKey().equals(authRepoId)) .filter(key -> key.getKey().equals(authRepoId))
.findFirst(); .findFirst();
if (!foundContact.isPresent()) { if (!foundContact.isPresent()) {
throw new BadAuthInfoForResourceException(); throw new BadAuthInfoForResourceException();

View file

@ -90,10 +90,10 @@ public final class ContactInfoFlow implements Flow {
.setVoiceNumber(contact.getVoiceNumber()) .setVoiceNumber(contact.getVoiceNumber())
.setFaxNumber(contact.getFaxNumber()) .setFaxNumber(contact.getFaxNumber())
.setEmailAddress(contact.getEmailAddress()) .setEmailAddress(contact.getEmailAddress())
.setCurrentSponsorClientId(contact.getCurrentSponsorRegistrarId()) .setCurrentSponsorRegistrarId(contact.getCurrentSponsorRegistrarId())
.setCreationClientId(contact.getCreationRegistrarId()) .setCreationRegistrarId(contact.getCreationRegistrarId())
.setCreationTime(contact.getCreationTime()) .setCreationTime(contact.getCreationTime())
.setLastEppUpdateClientId(contact.getLastEppUpdateRegistrarId()) .setLastEppUpdateRegistrarId(contact.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(contact.getLastEppUpdateTime()) .setLastEppUpdateTime(contact.getLastEppUpdateTime())
.setLastTransferTime(contact.getLastTransferTime()) .setLastTransferTime(contact.getLastTransferTime())
.setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null) .setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null)

View file

@ -608,7 +608,7 @@ public class DomainFlowUtils {
historyId, "Cannot create a new autorenew poll message without a domain history id"); historyId, "Cannot create a new autorenew poll message without a domain history id");
updatedAutorenewPollMessage = updatedAutorenewPollMessage =
newAutorenewPollMessage(domain) newAutorenewPollMessage(domain)
.setId((Long) domain.getAutorenewPollMessage().getSqlKey()) .setId((Long) domain.getAutorenewPollMessage().getKey())
.setAutorenewEndTime(newEndTime) .setAutorenewEndTime(newEndTime)
.setDomainHistoryId(historyId) .setDomainHistoryId(historyId)
.build(); .build();

View file

@ -111,7 +111,7 @@ public final class DomainInfoFlow implements Flow {
DomainInfoData.newBuilder() DomainInfoData.newBuilder()
.setDomainName(domain.getDomainName()) .setDomainName(domain.getDomainName())
.setRepoId(domain.getRepoId()) .setRepoId(domain.getRepoId())
.setCurrentSponsorClientId(domain.getCurrentSponsorRegistrarId()) .setCurrentSponsorRegistrarId(domain.getCurrentSponsorRegistrarId())
.setRegistrant( .setRegistrant(
tm().transact(() -> tm().loadByKey(domain.getRegistrant())).getContactId()); tm().transact(() -> tm().loadByKey(domain.getRegistrant())).getContactId());
// If authInfo is non-null, then the caller is authorized to see the full information since we // If authInfo is non-null, then the caller is authorized to see the full information since we
@ -125,9 +125,9 @@ public final class DomainInfoFlow implements Flow {
.setNameservers(hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null) .setNameservers(hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
.setSubordinateHosts( .setSubordinateHosts(
hostsRequest.requestSubordinate() ? domain.getSubordinateHosts() : null) hostsRequest.requestSubordinate() ? domain.getSubordinateHosts() : null)
.setCreationClientId(domain.getCreationRegistrarId()) .setCreationRegistrarId(domain.getCreationRegistrarId())
.setCreationTime(domain.getCreationTime()) .setCreationTime(domain.getCreationTime())
.setLastEppUpdateClientId(domain.getLastEppUpdateRegistrarId()) .setLastEppUpdateRegistrarId(domain.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(domain.getLastEppUpdateTime()) .setLastEppUpdateTime(domain.getLastEppUpdateTime())
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime()) .setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
.setLastTransferTime(domain.getLastTransferTime()) .setLastTransferTime(domain.getLastTransferTime())

View file

@ -151,7 +151,7 @@ public class AllocationTokenFlowUtils {
} }
maybeTokenEntity = maybeTokenEntity =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(AllocationToken.class, token))); tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
if (!maybeTokenEntity.isPresent()) { if (!maybeTokenEntity.isPresent()) {
throw new InvalidAllocationTokenException(); throw new InvalidAllocationTokenException();

View file

@ -80,14 +80,14 @@ public final class HostInfoFlow implements Flow {
tm().transact( tm().transact(
() -> tm().loadByKey(host.getSuperordinateDomain()).cloneProjectedAtTime(now)); () -> tm().loadByKey(host.getSuperordinateDomain()).cloneProjectedAtTime(now));
hostInfoDataBuilder hostInfoDataBuilder
.setCurrentSponsorClientId(superordinateDomain.getCurrentSponsorRegistrarId()) .setCurrentSponsorRegistrarId(superordinateDomain.getCurrentSponsorRegistrarId())
.setLastTransferTime(host.computeLastTransferTime(superordinateDomain)); .setLastTransferTime(host.computeLastTransferTime(superordinateDomain));
if (superordinateDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { if (superordinateDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
statusValues.add(StatusValue.PENDING_TRANSFER); statusValues.add(StatusValue.PENDING_TRANSFER);
} }
} else { } else {
hostInfoDataBuilder hostInfoDataBuilder
.setCurrentSponsorClientId(host.getPersistedCurrentSponsorRegistrarId()) .setCurrentSponsorRegistrarId(host.getPersistedCurrentSponsorRegistrarId())
.setLastTransferTime(host.getLastTransferTime()); .setLastTransferTime(host.getLastTransferTime());
} }
return responseBuilder return responseBuilder
@ -97,9 +97,9 @@ public final class HostInfoFlow implements Flow {
.setRepoId(host.getRepoId()) .setRepoId(host.getRepoId())
.setStatusValues(statusValues.build()) .setStatusValues(statusValues.build())
.setInetAddresses(host.getInetAddresses()) .setInetAddresses(host.getInetAddresses())
.setCreationClientId(host.getCreationRegistrarId()) .setCreationRegistrarId(host.getCreationRegistrarId())
.setCreationTime(host.getCreationTime()) .setCreationTime(host.getCreationTime())
.setLastEppUpdateClientId(host.getLastEppUpdateRegistrarId()) .setLastEppUpdateRegistrarId(host.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(host.getLastEppUpdateTime()) .setLastEppUpdateTime(host.getLastEppUpdateTime())
.build()) .build())
.build(); .build();

View file

@ -1,33 +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;
import com.google.common.collect.ImmutableSet;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.GaeUserIdConverter;
import google.registry.model.contact.Contact;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
@DeleteAfterMigration
public final class EntityClasses {
/** Set of entity classes. */
public static final ImmutableSet<Class<? extends ImmutableObject>> ALL_CLASSES =
ImmutableSet.of(Contact.class, Domain.class, GaeUserIdConverter.class, Host.class);
private EntityClasses() {}
}

View file

@ -31,11 +31,9 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import google.registry.config.RegistryConfig; import google.registry.config.RegistryConfig;
import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader; import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader;
import google.registry.model.annotations.OfyIdAllocation;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
@ -47,7 +45,6 @@ import java.util.Set;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.Transient; import javax.persistence.Transient;
@ -55,7 +52,7 @@ import org.joda.time.DateTime;
/** An EPP entity object (i.e. a domain, contact, or host). */ /** An EPP entity object (i.e. a domain, contact, or host). */
@MappedSuperclass @MappedSuperclass
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property) @Access(AccessType.FIELD) // otherwise it'll use the default of the repoId (property)
public abstract class EppResource extends UpdateAutoTimestampEntity implements Buildable { public abstract class EppResource extends UpdateAutoTimestampEntity implements Buildable {
private static final long serialVersionUID = -252782773382339534L; private static final long serialVersionUID = -252782773382339534L;
@ -70,7 +67,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* *
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a> * @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
*/ */
@Id @Transient String repoId; @OfyIdAllocation @Transient String repoId;
/** /**
* The ID of the registrar that is currently sponsoring this resource. * The ID of the registrar that is currently sponsoring this resource.
@ -78,9 +75,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null * <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
* resource fields. * resource fields.
*/ */
@Index String currentSponsorRegistrarId;
@Column(name = "currentSponsorRegistrarId")
String currentSponsorClientId;
/** /**
* The ID of the registrar that created this resource. * The ID of the registrar that created this resource.
@ -88,8 +83,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null * <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
* resource fields. * resource fields.
*/ */
@Column(name = "creationRegistrarId") String creationRegistrarId;
String creationClientId;
/** /**
* The ID of the registrar that last updated this resource. * The ID of the registrar that last updated this resource.
@ -98,8 +92,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* edits; it only includes EPP-visible modifications such as {@literal <update>}. Can be null if * edits; it only includes EPP-visible modifications such as {@literal <update>}. Can be null if
* the resource has never been modified. * the resource has never been modified.
*/ */
@Column(name = "lastEppUpdateRegistrarId") String lastEppUpdateRegistrarId;
String lastEppUpdateClientId;
/** /**
* The time when this resource was created. * The time when this resource was created.
@ -111,8 +104,8 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null * <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
* resource fields. * resource fields.
*/ */
@AttributeOverrides(@AttributeOverride(name = "creationTime", column = @Column)) // Need to override the default non-null column attribute.
@Ignore @AttributeOverride(name = "creationTime", column = @Column)
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null); CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
/** /**
@ -128,7 +121,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* out of the index at that time, as long as we query for resources whose deletion time is before * out of the index at that time, as long as we query for resources whose deletion time is before
* now. * now.
*/ */
@Index DateTime deletionTime; DateTime deletionTime;
/** /**
* The time that this resource was last updated. * The time that this resource was last updated.
@ -140,7 +133,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
DateTime lastEppUpdateTime; DateTime lastEppUpdateTime;
/** Status values associated with this resource. */ /** Status values associated with this resource. */
@Ignore Set<StatusValue> statuses; Set<StatusValue> statuses;
public String getRepoId() { public String getRepoId() {
return repoId; return repoId;
@ -164,7 +157,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
} }
public String getCreationRegistrarId() { public String getCreationRegistrarId() {
return creationClientId; return creationRegistrarId;
} }
public DateTime getLastEppUpdateTime() { public DateTime getLastEppUpdateTime() {
@ -172,17 +165,17 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
} }
public String getLastEppUpdateRegistrarId() { public String getLastEppUpdateRegistrarId() {
return lastEppUpdateClientId; return lastEppUpdateRegistrarId;
} }
/** /**
* Get the stored value of {@link #currentSponsorClientId}. * Get the stored value of {@link #currentSponsorRegistrarId}.
* *
* <p>For subordinate hosts, this value may not represent the actual current client id, which is * <p>For subordinate hosts, this value may not represent the actual current client id, which is
* the client id of the superordinate host. For all other resources this is the true client id. * the client id of the superordinate host. For all other resources this is the true client id.
*/ */
public final String getPersistedCurrentSponsorRegistrarId() { public final String getPersistedCurrentSponsorRegistrarId() {
return currentSponsorClientId; return currentSponsorRegistrarId;
} }
public final ImmutableSet<StatusValue> getStatusValues() { public final ImmutableSet<StatusValue> getStatusValues() {
@ -272,13 +265,13 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
/** Set the current sponsoring registrar. */ /** Set the current sponsoring registrar. */
public B setPersistedCurrentSponsorRegistrarId(String currentSponsorRegistrarId) { public B setPersistedCurrentSponsorRegistrarId(String currentSponsorRegistrarId) {
getInstance().currentSponsorClientId = currentSponsorRegistrarId; getInstance().currentSponsorRegistrarId = currentSponsorRegistrarId;
return thisCastToDerived(); return thisCastToDerived();
} }
/** Set the registrar that created this resource. */ /** Set the registrar that created this resource. */
public B setCreationRegistrarId(String creationRegistrarId) { public B setCreationRegistrarId(String creationRegistrarId) {
getInstance().creationClientId = creationRegistrarId; getInstance().creationRegistrarId = creationRegistrarId;
return thisCastToDerived(); return thisCastToDerived();
} }
@ -290,7 +283,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
/** Set the registrar who last performed a {@literal <update>} on this resource. */ /** Set the registrar who last performed a {@literal <update>} on this resource. */
public B setLastEppUpdateRegistrarId(String lastEppUpdateRegistrarId) { public B setLastEppUpdateRegistrarId(String lastEppUpdateRegistrarId) {
getInstance().lastEppUpdateClientId = lastEppUpdateRegistrarId; getInstance().lastEppUpdateRegistrarId = lastEppUpdateRegistrarId;
return thisCastToDerived(); return thisCastToDerived();
} }
@ -320,14 +313,14 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
/** Add to this resource's status values. */ /** Add to this resource's status values. */
public B addStatusValues(ImmutableSet<StatusValue> statusValues) { public B addStatusValues(ImmutableSet<StatusValue> statusValues) {
return setStatusValues(ImmutableSet.copyOf( return setStatusValues(
union(getInstance().getStatusValues(), statusValues))); ImmutableSet.copyOf(union(getInstance().getStatusValues(), statusValues)));
} }
/** Remove from this resource's status values. */ /** Remove from this resource's status values. */
public B removeStatusValues(ImmutableSet<StatusValue> statusValues) { public B removeStatusValues(ImmutableSet<StatusValue> statusValues) {
return setStatusValues(ImmutableSet.copyOf( return setStatusValues(
difference(getInstance().getStatusValues(), statusValues))); ImmutableSet.copyOf(difference(getInstance().getStatusValues(), statusValues)));
} }
/** Set this resource's repoId. */ /** Set this resource's repoId. */

View file

@ -26,7 +26,6 @@ import static google.registry.util.DateTimeUtils.latestOf;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import google.registry.config.RegistryConfig; import google.registry.config.RegistryConfig;
import google.registry.model.EppResource.BuilderWithTransferData; import google.registry.model.EppResource.BuilderWithTransferData;
import google.registry.model.EppResource.ForeignKeyedEppResource; import google.registry.model.EppResource.ForeignKeyedEppResource;
@ -359,7 +358,7 @@ public final class EppResourceUtils {
jpaTm() jpaTm()
.getEntityManager() .getEntityManager()
.createNativeQuery(HOST_LINKED_DOMAIN_QUERY) .createNativeQuery(HOST_LINKED_DOMAIN_QUERY)
.setParameter("fkRepoId", key.getSqlKey()) .setParameter("fkRepoId", key.getKey())
.setParameter("now", now.toDate()); .setParameter("now", now.toDate());
} }
if (limit != null) { if (limit != null) {
@ -370,9 +369,7 @@ public final class EppResourceUtils {
(ImmutableSet<VKey<Domain>>) (ImmutableSet<VKey<Domain>>)
query query
.getResultStream() .getResultStream()
.map( .map(repoId -> Domain.createVKey((String) repoId))
repoId ->
Domain.createVKey(Key.create(Domain.class, (String) repoId)))
.collect(toImmutableSet()); .collect(toImmutableSet());
return domainKeySet; return domainKeySet;
}); });

View file

@ -89,7 +89,7 @@ public final class ForeignKeyUtils {
Class<E> clazz, Collection<String> foreignKeys, final DateTime now) { Class<E> clazz, Collection<String> foreignKeys, final DateTime now) {
return load(clazz, foreignKeys, false).entrySet().stream() return load(clazz, foreignKeys, false).entrySet().stream()
.filter(e -> now.isBefore(e.getValue().deletionTime())) .filter(e -> now.isBefore(e.getValue().deletionTime()))
.collect(toImmutableMap(Entry::getKey, e -> VKey.createSql(clazz, e.getValue().repoId()))); .collect(toImmutableMap(Entry::getKey, e -> VKey.create(clazz, e.getValue().repoId())));
} }
/** /**
@ -146,16 +146,14 @@ public final class ForeignKeyUtils {
// called, it is always passed with a list of VKeys with the same type. // called, it is always passed with a list of VKeys with the same type.
Class<? extends EppResource> clazz = keys.iterator().next().getKind(); Class<? extends EppResource> clazz = keys.iterator().next().getKind();
ImmutableList<String> foreignKeys = ImmutableList<String> foreignKeys =
Streams.stream(keys) Streams.stream(keys).map(key -> (String) key.getKey()).collect(toImmutableList());
.map(key -> (String) key.getSqlKey())
.collect(toImmutableList());
ImmutableMap<String, MostRecentResource> existingKeys = ImmutableMap<String, MostRecentResource> existingKeys =
ForeignKeyUtils.load(clazz, foreignKeys, true); ForeignKeyUtils.load(clazz, foreignKeys, true);
// The above map only contains keys that exist in the database, so we re-add the // The above map only contains keys that exist in the database, so we re-add the
// missing ones with Optional.empty() values for caching. // missing ones with Optional.empty() values for caching.
return Maps.asMap( return Maps.asMap(
ImmutableSet.copyOf(keys), ImmutableSet.copyOf(keys),
key -> Optional.ofNullable(existingKeys.get((String) key.getSqlKey()))); key -> Optional.ofNullable(existingKeys.get((String) key.getKey())));
} }
}; };
@ -211,15 +209,14 @@ public final class ForeignKeyUtils {
return load(clazz, foreignKeys, now); return load(clazz, foreignKeys, now);
} }
return foreignKeyCache return foreignKeyCache
.getAll( .getAll(foreignKeys.stream().map(fk -> VKey.create(clazz, fk)).collect(toImmutableList()))
foreignKeys.stream().map(fk -> VKey.createSql(clazz, fk)).collect(toImmutableList()))
.entrySet() .entrySet()
.stream() .stream()
.filter(e -> e.getValue().isPresent() && now.isBefore(e.getValue().get().deletionTime())) .filter(e -> e.getValue().isPresent() && now.isBefore(e.getValue().get().deletionTime()))
.collect( .collect(
toImmutableMap( toImmutableMap(
e -> (String) e.getKey().getSqlKey(), e -> (String) e.getKey().getKey(),
e -> VKey.createSql(clazz, e.getValue().get().repoId()))); e -> VKey.create(clazz, e.getValue().get().repoId())));
} }
@AutoValue @AutoValue

View file

@ -183,11 +183,11 @@ public final class ResourceTransferUtils {
* sets the last EPP update client id to the given client id. * sets the last EPP update client id to the given client id.
*/ */
public static <R extends EppResource & ResourceWithTransferData> R denyPendingTransfer( public static <R extends EppResource & ResourceWithTransferData> R denyPendingTransfer(
R resource, TransferStatus transferStatus, DateTime now, String lastEppUpdateClientId) { R resource, TransferStatus transferStatus, DateTime now, String lastEppUpdateRegistrarId) {
checkArgument(transferStatus.isDenied(), "Not a denial transfer status"); checkArgument(transferStatus.isDenied(), "Not a denial transfer status");
return resolvePendingTransfer(resource, transferStatus, now) return resolvePendingTransfer(resource, transferStatus, now)
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateRegistrarId(lastEppUpdateClientId) .setLastEppUpdateRegistrarId(lastEppUpdateRegistrarId)
.build(); .build();
} }
} }

View file

@ -1,69 +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;
import static com.google.common.base.Predicates.or;
import static com.google.common.base.Predicates.subtypeOf;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.Ordering;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.SortedSet;
import java.util.TreeSet;
/** Utility methods for getting the version of the model schema from the model code. */
@DeleteAfterMigration
public final class SchemaVersion {
/**
* Returns a set of classes corresponding to all types persisted within the model classes, sorted
* by the string representation.
*/
private static SortedSet<Class<?>> getAllPersistedTypes() {
SortedSet<Class<?>> persistedTypes = new TreeSet<>(Ordering.usingToString());
// Do a breadth-first search for persisted types, starting with @Entity types and expanding each
// ImmutableObject by querying it for all its persisted field types.
persistedTypes.addAll(EntityClasses.ALL_CLASSES);
Queue<Class<?>> queue = new ArrayDeque<>(persistedTypes);
while (!queue.isEmpty()) {
Class<?> clazz = queue.remove();
if (ImmutableObject.class.isAssignableFrom(clazz)) {
for (Class<?> persistedFieldType : ModelUtils.getPersistedFieldTypes(clazz)) {
if (persistedTypes.add(persistedFieldType)) {
// If we haven't seen this type before, add it to the queue to query its field types.
queue.add(persistedFieldType);
}
}
}
}
return persistedTypes;
}
/**
* Return a string representing the schema which includes the definition of all persisted entity
* types (and their field types, recursively). Each definition contains the field names and their
* types (for classes), or else a list of all possible values (for enums).
*/
public static String getSchema() {
return getAllPersistedTypes().stream()
.filter(or(subtypeOf(Enum.class), subtypeOf(ImmutableObject.class)))
.map(ModelUtils::getSchema)
.collect(joining("\n"));
}
private SchemaVersion() {}
}

View file

@ -375,7 +375,7 @@ public abstract class BillingEvent extends ImmutableObject
} }
public static VKey<OneTime> createVKey(long id) { public static VKey<OneTime> createVKey(long id) {
return VKey.createSql(OneTime.class, id); return VKey.create(OneTime.class, id);
} }
@Override @Override
@ -538,7 +538,7 @@ public abstract class BillingEvent extends ImmutableObject
} }
public static VKey<Recurring> createVKey(Long id) { public static VKey<Recurring> createVKey(Long id) {
return VKey.createSql(Recurring.class, id); return VKey.create(Recurring.class, id);
} }
@Override @Override
@ -682,7 +682,7 @@ public abstract class BillingEvent extends ImmutableObject
} }
public static VKey<Cancellation> createVKey(long id) { public static VKey<Cancellation> createVKey(long id) {
return VKey.createSql(Cancellation.class, id); return VKey.create(Cancellation.class, id);
} }
@Override @Override

View file

@ -1,68 +0,0 @@
// Copyright 2021 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.common;
import static com.google.common.base.Functions.identity;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.EntityClasses.ALL_CLASSES;
import com.google.common.annotations.VisibleForTesting;
import com.googlecode.objectify.annotation.EntitySubclass;
import java.util.Map;
import java.util.stream.Collectors;
/** A helper to manage class name and class path mapping. */
public class ClassPathManager {
/**
* Class registry allowing us to restore the original class object from the unqualified class
* name, which is all the datastore key gives us. Note that entities annotated
* with @EntitySubclass are removed because they share the same kind of the key with their parent
* class.
*/
public static final Map<String, Class<?>> CLASS_REGISTRY =
ALL_CLASSES.stream()
.filter(clazz -> !clazz.isAnnotationPresent(EntitySubclass.class))
.collect(Collectors.toMap(com.googlecode.objectify.Key::getKind, identity()));
/**
* Class name registry allowing us to obtain the class name the unqualified class, which is all
* the datastore key gives us. Note that entities annotated with @EntitySubclass are removed
* because they share the same kind of the key with their parent class.
*/
public static final Map<Class<?>, String> CLASS_NAME_REGISTRY =
ALL_CLASSES.stream()
.filter(clazz -> !clazz.isAnnotationPresent(EntitySubclass.class))
.collect(Collectors.toMap(identity(), com.googlecode.objectify.Key::getKind));
@VisibleForTesting
public static void addTestEntityClass(Class<?> clazz) {
CLASS_REGISTRY.put(clazz.getSimpleName(), clazz);
CLASS_NAME_REGISTRY.put(clazz, clazz.getSimpleName());
}
public static <T> Class<T> getClass(String className) {
checkArgument(
CLASS_REGISTRY.containsKey(className), "Class %s not found in class registry", className);
return (Class<T>) CLASS_REGISTRY.get(className);
}
public static <T> String getClassName(Class<T> clazz) {
checkArgument(
CLASS_NAME_REGISTRY.containsKey(clazz),
"Class %s not found in class name registry",
clazz.getSimpleName());
return CLASS_NAME_REGISTRY.get(clazz);
}
}

View file

@ -14,22 +14,15 @@
package google.registry.model.common; package google.registry.model.common;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration; import javax.persistence.Id;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
/** /** A singleton entity in the database. */
* A singleton entity in the database.
*
* <p>This class should not be deleted after the migration, because there is still a concept of
* singleton in SQL. We should remove the ofy @Id annotation after all of its subclass are Ofy-free.
*/
@DeleteAfterMigration
@MappedSuperclass @MappedSuperclass
public abstract class CrossTldSingleton extends ImmutableObject { public abstract class CrossTldSingleton extends ImmutableObject {
public static final long SINGLETON_ID = 1; // There is always exactly one of these. public static final long SINGLETON_ID = 1; // There is always exactly one of these.
@Id @javax.persistence.Id long id = SINGLETON_ID; @Id long id = SINGLETON_ID;
} }

View file

@ -141,7 +141,7 @@ public class Cursor extends UpdateAutoTimestampEntity {
private static VKey<Cursor> createVKey(CursorType type, String scope) { private static VKey<Cursor> createVKey(CursorType type, String scope) {
checkValidCursorTypeForScope(type, scope); checkValidCursorTypeForScope(type, scope);
return VKey.createSql(Cursor.class, new CursorId(type, scope)); return VKey.create(Cursor.class, new CursorId(type, scope));
} }
public DateTime getLastUpdateTime() { public DateTime getLastUpdateTime() {

View file

@ -16,7 +16,6 @@ package google.registry.model.contact;
import google.registry.model.EppResource.ForeignKeyedEppResource; import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName; import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.annotations.ReportedOn;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.persistence.WithVKey; import google.registry.persistence.WithVKey;
import javax.persistence.Access; import javax.persistence.Access;
@ -32,9 +31,7 @@ import org.joda.time.DateTime;
* *
* @see <a href="https://tools.ietf.org/html/rfc5733">RFC 5733</a> * @see <a href="https://tools.ietf.org/html/rfc5733">RFC 5733</a>
*/ */
@ReportedOn
@Entity @Entity
@com.googlecode.objectify.annotation.Entity
@Table( @Table(
name = "Contact", name = "Contact",
indexes = { indexes = {
@ -51,7 +48,7 @@ public class Contact extends ContactBase implements ForeignKeyedEppResource {
@Override @Override
public VKey<Contact> createVKey() { public VKey<Contact> createVKey() {
return VKey.createSql(Contact.class, getRepoId()); return VKey.create(Contact.class, getRepoId());
} }
@Override @Override

View file

@ -19,11 +19,6 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime; import static google.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.OnLoad;
import com.googlecode.objectify.condition.IfNull;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.EppResource.ResourceWithTransferData; import google.registry.model.EppResource.ResourceWithTransferData;
import google.registry.model.transfer.ContactTransferData; import google.registry.model.transfer.ContactTransferData;
@ -54,7 +49,8 @@ import org.joda.time.DateTime;
@MappedSuperclass @MappedSuperclass
@Embeddable @Embeddable
@Access(AccessType.FIELD) @Access(AccessType.FIELD)
public class ContactBase extends EppResource implements ResourceWithTransferData { public class ContactBase extends EppResource
implements ResourceWithTransferData<ContactTransferData> {
/** /**
* Unique identifier for this contact. * Unique identifier for this contact.
@ -69,7 +65,6 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
* Localized postal info for the contact. All contained values must be representable in the 7-bit * Localized postal info for the contact. All contained values must be representable in the 7-bit
* US-ASCII character set. Personal info; cleared by {@link Contact.Builder#wipeOut}. * US-ASCII character set. Personal info; cleared by {@link Contact.Builder#wipeOut}.
*/ */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "name", column = @Column(name = "addr_local_name")), @AttributeOverride(name = "name", column = @Column(name = "addr_local_name")),
@ -97,7 +92,6 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
* Internationalized postal info for the contact. Personal info; cleared by {@link * Internationalized postal info for the contact. Personal info; cleared by {@link
* Contact.Builder#wipeOut}. * Contact.Builder#wipeOut}.
*/ */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "name", column = @Column(name = "addr_i18n_name")), @AttributeOverride(name = "name", column = @Column(name = "addr_i18n_name")),
@ -126,10 +120,9 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
* postal name, or if null, the localized postal name, or if that is null as well, null. Personal * postal name, or if null, the localized postal name, or if that is null as well, null. Personal
* info; cleared by {@link Contact.Builder#wipeOut}. * info; cleared by {@link Contact.Builder#wipeOut}.
*/ */
@Index String searchName; String searchName;
/** Contacts voice number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ /** Contacts voice number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "phoneNumber", column = @Column(name = "voice_phone_number")), @AttributeOverride(name = "phoneNumber", column = @Column(name = "voice_phone_number")),
@ -138,7 +131,6 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
ContactPhoneNumber voice; ContactPhoneNumber voice;
/** Contacts fax number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ /** Contacts fax number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "phoneNumber", column = @Column(name = "fax_phone_number")), @AttributeOverride(name = "phoneNumber", column = @Column(name = "fax_phone_number")),
@ -147,11 +139,9 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
ContactPhoneNumber fax; ContactPhoneNumber fax;
/** Contacts email address. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ /** Contacts email address. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
@IgnoreSave(IfNull.class)
String email; String email;
/** Authorization info (aka transfer secret) of the contact. */ /** Authorization info (aka transfer secret) of the contact. */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")), @AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")),
@ -160,7 +150,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
ContactAuthInfo authInfo; ContactAuthInfo authInfo;
/** Data about any pending or past transfers on this contact. */ /** Data about any pending or past transfers on this contact. */
@Ignore ContactTransferData transferData; ContactTransferData transferData;
/** /**
* The time that this resource was last transferred. * The time that this resource was last transferred.
@ -173,7 +163,6 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
// the wipeOut() function, so that data is not kept around for deleted contacts. // the wipeOut() function, so that data is not kept around for deleted contacts.
/** Disclosure policy. */ /** Disclosure policy. */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "name", column = @Column(name = "disclose_types_name")), @AttributeOverride(name = "name", column = @Column(name = "disclose_types_name")),
@ -193,17 +182,6 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
+ " use Contact instead"); + " use Contact instead");
} }
@OnLoad
void onLoad() {
if (voice != null && voice.hasNullFields()) {
voice = null;
}
if (fax != null && fax.hasNullFields()) {
fax = null;
}
}
public String getContactId() { public String getContactId() {
return contactId; return contactId;
} }

View file

@ -68,7 +68,7 @@ public class ContactHistory extends HistoryEntry {
/** Creates a {@link VKey} instance for this entity. */ /** Creates a {@link VKey} instance for this entity. */
@Override @Override
public VKey<ContactHistory> createVKey() { public VKey<ContactHistory> createVKey() {
return VKey.createSql(ContactHistory.class, getHistoryEntryId()); return VKey.create(ContactHistory.class, getHistoryEntryId());
} }
@Override @Override

View file

@ -30,7 +30,8 @@ import org.joda.time.DateTime;
/** The {@link ResponseData} returned for an EPP info flow on a contact. */ /** The {@link ResponseData} returned for an EPP info flow on a contact. */
@XmlRootElement(name = "infData") @XmlRootElement(name = "infData")
@XmlType(propOrder = { @XmlType(
propOrder = {
"contactId", "contactId",
"repoId", "repoId",
"statusValues", "statusValues",
@ -38,14 +39,15 @@ import org.joda.time.DateTime;
"voiceNumber", "voiceNumber",
"faxNumber", "faxNumber",
"emailAddress", "emailAddress",
"currentSponsorClientId", "currentSponsorRegistrarId",
"creationClientId", "creationRegistrarId",
"creationTime", "creationTime",
"lastEppUpdateClientId", "lastEppUpdateRegistrarId",
"lastEppUpdateTime", "lastEppUpdateTime",
"lastTransferTime", "lastTransferTime",
"authInfo", "authInfo",
"disclose" }) "disclose"
})
@AutoValue @AutoValue
@CopyAnnotations @CopyAnnotations
public abstract class ContactInfoData implements ResponseData { public abstract class ContactInfoData implements ResponseData {
@ -76,17 +78,17 @@ public abstract class ContactInfoData implements ResponseData {
abstract String getEmailAddress(); abstract String getEmailAddress();
@XmlElement(name = "clID") @XmlElement(name = "clID")
abstract String getCurrentSponsorClientId(); abstract String getCurrentSponsorRegistrarId();
@XmlElement(name = "crID") @XmlElement(name = "crID")
abstract String getCreationClientId(); abstract String getCreationRegistrarId();
@XmlElement(name = "crDate") @XmlElement(name = "crDate")
abstract DateTime getCreationTime(); abstract DateTime getCreationTime();
@XmlElement(name = "upID") @XmlElement(name = "upID")
@Nullable @Nullable
abstract String getLastEppUpdateClientId(); abstract String getLastEppUpdateRegistrarId();
@XmlElement(name = "upDate") @XmlElement(name = "upDate")
@Nullable @Nullable
@ -114,10 +116,15 @@ public abstract class ContactInfoData implements ResponseData {
public abstract Builder setVoiceNumber(@Nullable ContactPhoneNumber voiceNumber); public abstract Builder setVoiceNumber(@Nullable ContactPhoneNumber voiceNumber);
public abstract Builder setFaxNumber(@Nullable ContactPhoneNumber faxNumber); public abstract Builder setFaxNumber(@Nullable ContactPhoneNumber faxNumber);
public abstract Builder setEmailAddress(@Nullable String emailAddress); public abstract Builder setEmailAddress(@Nullable String emailAddress);
public abstract Builder setCurrentSponsorClientId(String currentSponsorClientId);
public abstract Builder setCreationClientId(String creationClientId); public abstract Builder setCurrentSponsorRegistrarId(String currentSponsorRegistrarId);
public abstract Builder setCreationRegistrarId(String creationRegistrarId);
public abstract Builder setCreationTime(DateTime creationTime); public abstract Builder setCreationTime(DateTime creationTime);
public abstract Builder setLastEppUpdateClientId(@Nullable String lastEppUpdateClientId);
public abstract Builder setLastEppUpdateRegistrarId(@Nullable String lastEppUpdateRegistrarId);
public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime); public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime);
public abstract Builder setLastTransferTime(@Nullable DateTime lastTransferTime); public abstract Builder setLastTransferTime(@Nullable DateTime lastTransferTime);
public abstract Builder setAuthInfo(@Nullable ContactAuthInfo authInfo); public abstract Builder setAuthInfo(@Nullable ContactAuthInfo authInfo);

View file

@ -16,9 +16,7 @@ package google.registry.model.domain;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable; import google.registry.model.UnsafeSerializable;
import google.registry.model.contact.Contact; import google.registry.model.contact.Contact;
@ -66,13 +64,11 @@ public class DesignatedContact extends ImmutableObject implements UnsafeSerializ
DesignatedContact instance = new DesignatedContact(); DesignatedContact instance = new DesignatedContact();
instance.type = type; instance.type = type;
instance.contactVKey = checkArgumentNotNull(contact, "Must specify contact key"); instance.contactVKey = checkArgumentNotNull(contact, "Must specify contact key");
instance.contact = contact.maybeGetOfyKey().orElse(null);
return instance; return instance;
} }
Type type; Type type;
@Index Key<Contact> contact;
@Ignore VKey<Contact> contactVKey; @Ignore VKey<Contact> contactVKey;
public Type getType() { public Type getType() {
@ -82,8 +78,4 @@ public class DesignatedContact extends ImmutableObject implements UnsafeSerializ
public VKey<Contact> getContactKey() { public VKey<Contact> getContactKey() {
return contactVKey; return contactVKey;
} }
public DesignatedContact reconstitute() {
return create(type, VKey.from(contact));
}
} }

View file

@ -14,11 +14,9 @@
package google.registry.model.domain; package google.registry.model.domain;
import com.googlecode.objectify.Key;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.EppResource.ForeignKeyedEppResource; import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName; import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.domain.secdns.DomainDsData; import google.registry.model.domain.secdns.DomainDsData;
import google.registry.model.host.Host; import google.registry.model.host.Host;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
@ -31,6 +29,7 @@ import javax.persistence.Column;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Index; import javax.persistence.Index;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
@ -45,8 +44,6 @@ import org.joda.time.DateTime;
* *
* @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a> * @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a>
*/ */
@ReportedOn
@com.googlecode.objectify.annotation.Entity
@Entity @Entity
@Table( @Table(
name = "Domain", name = "Domain",
@ -72,7 +69,7 @@ import org.joda.time.DateTime;
public class Domain extends DomainBase implements ForeignKeyedEppResource { public class Domain extends DomainBase implements ForeignKeyedEppResource {
@Override @Override
@javax.persistence.Id @Id
@Access(AccessType.PROPERTY) @Access(AccessType.PROPERTY)
public String getRepoId() { public String getRepoId() {
return super.getRepoId(); return super.getRepoId();
@ -110,7 +107,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
referencedColumnName = "repoId", referencedColumnName = "repoId",
insertable = false, insertable = false,
updatable = false) updatable = false)
@SuppressWarnings("UnusedMethod") @SuppressWarnings("unused")
private Set<GracePeriod> getInternalGracePeriods() { private Set<GracePeriod> getInternalGracePeriods() {
return gracePeriods; return gracePeriods;
} }
@ -132,7 +129,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
referencedColumnName = "repoId", referencedColumnName = "repoId",
insertable = false, insertable = false,
updatable = false) updatable = false)
@SuppressWarnings("UnusedMethod") @SuppressWarnings("unused")
private Set<DomainDsData> getInternalDelegationSignerData() { private Set<DomainDsData> getInternalDelegationSignerData() {
return dsData; return dsData;
} }
@ -147,7 +144,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
@Override @Override
public VKey<Domain> createVKey() { public VKey<Domain> createVKey() {
return VKey.createSql(Domain.class, getRepoId()); return VKey.create(Domain.class, getRepoId());
} }
@Override @Override
@ -155,8 +152,8 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
return cloneDomainProjectedAtTime(this, now); return cloneDomainProjectedAtTime(this, now);
} }
public static VKey<Domain> createVKey(Key<Domain> key) { public static VKey<Domain> createVKey(String repoId) {
return VKey.create(Domain.class, key.getName(), key); return VKey.create(Domain.class, repoId);
} }
/** An override of {@link EppResource#asBuilder} with tighter typing. */ /** An override of {@link EppResource#asBuilder} with tighter typing. */

View file

@ -36,20 +36,15 @@ import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static google.registry.util.DomainNameUtils.getTldFromDomainName; import static google.registry.util.DomainNameUtils.getTldFromDomainName;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.condition.IfNull;
import google.registry.dns.RefreshDnsAction; import google.registry.dns.RefreshDnsAction;
import google.registry.flows.ResourceFlowUtils; import google.registry.flows.ResourceFlowUtils;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.EppResource.ResourceWithTransferData; import google.registry.model.EppResource.ResourceWithTransferData;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.contact.Contact; import google.registry.model.contact.Contact;
import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
@ -59,16 +54,20 @@ import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.Host; import google.registry.model.host.Host;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.poll.PollMessage.Autorenew;
import google.registry.model.poll.PollMessage.OneTime;
import google.registry.model.tld.Registry; import google.registry.model.tld.Registry;
import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.tldconfig.idn.IdnLabelValidator;
import google.registry.util.CollectionUtils; import google.registry.util.CollectionUtils;
import google.registry.util.DateTimeUtils; import google.registry.util.DateTimeUtils;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
@ -77,6 +76,7 @@ import javax.persistence.AttributeOverrides;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.Embedded; import javax.persistence.Embedded;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.hibernate.collection.internal.PersistentSet; import org.hibernate.collection.internal.PersistentSet;
@ -86,9 +86,9 @@ import org.joda.time.Interval;
/** /**
* A persistable domain resource including mutable and non-mutable fields. * A persistable domain resource including mutable and non-mutable fields.
* *
* <p>This class deliberately does not include an {@link javax.persistence.Id} so that any * <p>This class deliberately does not include an {@link Id} so that any foreign-keyed fields can
* foreign-keyed fields can refer to the proper parent entity's ID, whether we're storing this in * refer to the proper parent entity's ID, whether we're storing this in the DB itself or as part of
* the DB itself or as part of another entity. * another entity.
* *
* @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a> * @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a>
*/ */
@ -118,13 +118,13 @@ public class DomainBase extends EppResource
* *
* @invariant domainName == domainName.toLowerCase(Locale.ENGLISH) * @invariant domainName == domainName.toLowerCase(Locale.ENGLISH)
*/ */
@Index String domainName; String domainName;
/** The top level domain this is under, dernormalized from {@link #domainName}. */ /** The top level domain this is under, de-normalized from {@link #domainName}. */
@Index String tld; String tld;
/** References to hosts that are the nameservers for the domain. */ /** References to hosts that are the nameservers for the domain. */
@EmptySetToNull @Index @Transient Set<VKey<Host>> nsHosts; @EmptySetToNull @Transient Set<VKey<Host>> nsHosts;
/** Contacts. */ /** Contacts. */
VKey<Contact> adminContact; VKey<Contact> adminContact;
@ -134,7 +134,6 @@ public class DomainBase extends EppResource
VKey<Contact> registrantContact; VKey<Contact> registrantContact;
/** Authorization info (aka transfer secret) of the domain. */ /** Authorization info (aka transfer secret) of the domain. */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")), @AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")),
@ -143,14 +142,13 @@ public class DomainBase extends EppResource
DomainAuthInfo authInfo; DomainAuthInfo authInfo;
/** Data used to construct DS records for this domain. */ /** Data used to construct DS records for this domain. */
@Ignore @Transient Set<DomainDsData> dsData; @Transient Set<DomainDsData> dsData;
/** /**
* The claims notice supplied when this domain was created, if there was one. * The claims notice supplied when this domain was created, if there was one.
* *
* <p>It's {@literal @}XmlTransient because it's not returned in an info response. * <p>It's {@literal @}XmlTransient because it's not returned in an info response.
*/ */
@Ignore
@Embedded @Embedded
@AttributeOverrides({ @AttributeOverrides({
@AttributeOverride(name = "noticeId.tcnId", column = @Column(name = "launch_notice_tcn_id")), @AttributeOverride(name = "noticeId.tcnId", column = @Column(name = "launch_notice_tcn_id")),
@ -169,9 +167,8 @@ public class DomainBase extends EppResource
/** /**
* Name of first IDN table associated with TLD that matched the characters in this domain label. * Name of first IDN table associated with TLD that matched the characters in this domain label.
* *
* @see google.registry.tldconfig.idn.IdnLabelValidator#findValidIdnTableForTld * @see IdnLabelValidator#findValidIdnTableForTld
*/ */
@IgnoreSave(IfNull.class)
String idnTableName; String idnTableName;
/** Fully qualified host names of this domain's active subordinate hosts. */ /** Fully qualified host names of this domain's active subordinate hosts. */
@ -188,44 +185,42 @@ public class DomainBase extends EppResource
* restored, the message should be deleted. * restored, the message should be deleted.
*/ */
@Column(name = "deletion_poll_message_id") @Column(name = "deletion_poll_message_id")
VKey<PollMessage.OneTime> deletePollMessage; VKey<OneTime> deletePollMessage;
/** /**
* The recurring billing event associated with this domain's autorenewals. * The recurring billing event associated with this domain's autorenewals.
* *
* <p>The recurrence should be open ended unless the domain is in pending delete or fully deleted, * <p>The recurrence should be open-ended unless the domain is in pending delete or fully deleted,
* in which case it should be closed at the time the delete was requested. Whenever the domain's * in which case it should be closed at the time the delete was requested. Whenever the domain's
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one * {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one. * should be created, and this field should be updated to point to the new one.
*/ */
@Column(name = "billing_recurrence_id") @Column(name = "billing_recurrence_id")
@Ignore VKey<Recurring> autorenewBillingEvent;
VKey<BillingEvent.Recurring> autorenewBillingEvent;
/** /**
* The recurring poll message associated with this domain's autorenewals. * The recurring poll message associated with this domain's autorenewals.
* *
* <p>The recurrence should be open ended unless the domain is in pending delete or fully deleted, * <p>The recurrence should be open-ended unless the domain is in pending delete or fully deleted,
* in which case it should be closed at the time the delete was requested. Whenever the domain's * in which case it should be closed at the time the delete was requested. Whenever the domain's
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one * {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one. * should be created, and this field should be updated to point to the new one.
*/ */
@Column(name = "autorenew_poll_message_id") @Column(name = "autorenew_poll_message_id")
VKey<PollMessage.Autorenew> autorenewPollMessage; VKey<Autorenew> autorenewPollMessage;
/** The unexpired grace periods for this domain (some of which may not be active yet). */ /** The unexpired grace periods for this domain (some of which may not be active yet). */
@Ignore @Transient Set<GracePeriod> gracePeriods; @Transient Set<GracePeriod> gracePeriods;
/** /**
* The id of the signed mark that was used to create this domain in sunrise. * The id of the signed mark that was used to create this domain in sunrise.
* *
* <p>Will only be populated for domains created in sunrise. * <p>Will only be populated for domains created in sunrise.
*/ */
@IgnoreSave(IfNull.class)
String smdId; String smdId;
/** Data about any pending or past transfers on this domain. */ /** Data about any pending or past transfers on this domain. */
@Ignore DomainTransferData transferData; DomainTransferData transferData;
/** /**
* The time that this resource was last transferred. * The time that this resource was last transferred.
@ -249,12 +244,12 @@ public class DomainBase extends EppResource
* difference domains that have reached their life and must be deleted now, and domains that * difference domains that have reached their life and must be deleted now, and domains that
* happen to be in the autorenew grace period now but should be deleted in roughly a year. * happen to be in the autorenew grace period now but should be deleted in roughly a year.
*/ */
@Index DateTime autorenewEndTime; DateTime autorenewEndTime;
/** /**
* When this domain's DNS was requested to be refreshed, or null if its DNS is up-to-date. * When this domain's DNS was requested to be refreshed, or null if its DNS is up-to-date.
* *
* <p>This will almost always be null except in the couple minutes' interval between when a * <p>This will almost always be null except in the couple of minutes' interval between when a
* DNS-affecting create or update operation takes place and when the {@link RefreshDnsAction} * DNS-affecting create or update operation takes place and when the {@link RefreshDnsAction}
* runs, which resets this back to null upon completion of the DNS refresh task. This is a {@link * runs, which resets this back to null upon completion of the DNS refresh task. This is a {@link
* DateTime} rather than a simple dirty boolean so that the DNS refresh action can order by the * DateTime} rather than a simple dirty boolean so that the DNS refresh action can order by the
@ -271,10 +266,10 @@ public class DomainBase extends EppResource
* it remains as a permanent record of which actions were DNS-affecting and which were not. * it remains as a permanent record of which actions were DNS-affecting and which were not.
*/ */
// TODO(mcilwain): Start using this field once we are further along in the DB migration. // TODO(mcilwain): Start using this field once we are further along in the DB migration.
@Ignore DateTime dnsRefreshRequestTime; DateTime dnsRefreshRequestTime;
/** The {@link AllocationToken} for the package this domain is currently a part of. */ /** The {@link AllocationToken} for the package this domain is currently a part of. */
@Ignore @Nullable VKey<AllocationToken> currentPackageToken; @Nullable VKey<AllocationToken> currentPackageToken;
/** /**
* Returns the DNS refresh request time iff this domain's DNS needs refreshing, otherwise absent. * Returns the DNS refresh request time iff this domain's DNS needs refreshing, otherwise absent.
@ -291,15 +286,15 @@ public class DomainBase extends EppResource
return registrationExpirationTime; return registrationExpirationTime;
} }
public VKey<PollMessage.OneTime> getDeletePollMessage() { public VKey<OneTime> getDeletePollMessage() {
return deletePollMessage; return deletePollMessage;
} }
public VKey<BillingEvent.Recurring> getAutorenewBillingEvent() { public VKey<Recurring> getAutorenewBillingEvent() {
return autorenewBillingEvent; return autorenewBillingEvent;
} }
public VKey<PollMessage.Autorenew> getAutorenewPollMessage() { public VKey<Autorenew> getAutorenewPollMessage() {
return autorenewPollMessage; return autorenewPollMessage;
} }
@ -362,7 +357,7 @@ public class DomainBase extends EppResource
} }
// Hibernate needs this in order to populate nsHosts but no one else should ever use it // Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("UnusedMethod") @SuppressWarnings("unused")
private void setNsHosts(Set<VKey<Host>> nsHosts) { private void setNsHosts(Set<VKey<Host>> nsHosts) {
this.nsHosts = forceEmptyToNull(nsHosts); this.nsHosts = forceEmptyToNull(nsHosts);
} }
@ -370,14 +365,14 @@ public class DomainBase extends EppResource
// Note: for the two methods below, how we wish to treat the Hibernate setters depends on the // Note: for the two methods below, how we wish to treat the Hibernate setters depends on the
// current state of the object and what's passed in. The key principle is that we wish to maintain // current state of the object and what's passed in. The key principle is that we wish to maintain
// the link between parent and child objects, meaning that we should keep around whichever of the // the link between parent and child objects, meaning that we should keep around whichever of the
// two sets (the parameter vs the class variable and clear/populate that as appropriate. // two sets (the parameter vs the class variable and clear/populate that as appropriate).
// //
// If the class variable is a PersistentSet and we overwrite it here, Hibernate will throw // If the class variable is a PersistentSet, and we overwrite it here, Hibernate will throw
// an exception "A collection with cascade=”all-delete-orphan” was no longer referenced by the // an exception "A collection with cascade=”all-delete-orphan” was no longer referenced by the
// owning entity instance". See https://stackoverflow.com/questions/5587482 for more details. // owning entity instance". See https://stackoverflow.com/questions/5587482 for more details.
// Hibernate needs this in order to populate gracePeriods but no one else should ever use it // Hibernate needs this in order to populate gracePeriods but no one else should ever use it
@SuppressWarnings("UnusedMethod") @SuppressWarnings("unused")
private void setInternalGracePeriods(Set<GracePeriod> gracePeriods) { private void setInternalGracePeriods(Set<GracePeriod> gracePeriods) {
if (this.gracePeriods instanceof PersistentSet) { if (this.gracePeriods instanceof PersistentSet) {
Set<GracePeriod> nonNullGracePeriods = nullToEmpty(gracePeriods); Set<GracePeriod> nonNullGracePeriods = nullToEmpty(gracePeriods);
@ -389,7 +384,7 @@ public class DomainBase extends EppResource
} }
// Hibernate needs this in order to populate dsData but no one else should ever use it // Hibernate needs this in order to populate dsData but no one else should ever use it
@SuppressWarnings("UnusedMethod") @SuppressWarnings("unused")
private void setInternalDelegationSignerData(Set<DomainDsData> dsData) { private void setInternalDelegationSignerData(Set<DomainDsData> dsData) {
if (this.dsData instanceof PersistentSet) { if (this.dsData instanceof PersistentSet) {
Set<DomainDsData> nonNullDsData = nullToEmpty(dsData); Set<DomainDsData> nonNullDsData = nullToEmpty(dsData);
@ -488,7 +483,7 @@ public class DomainBase extends EppResource
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) .setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent())
.setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage()); .setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage());
if (transferData.getTransferPeriod().getValue() == 1) { if (transferData.getTransferPeriod().getValue() == 1) {
// Set the grace period using a key to the prescheduled transfer billing event. Not using // Set the grace period using a key to the pre-scheduled transfer billing event. Not using
// GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch. // GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch.
builder.setGracePeriods( builder.setGracePeriods(
ImmutableSet.of( ImmutableSet.of(
@ -551,7 +546,7 @@ public class DomainBase extends EppResource
} }
} }
// It is possible that the lastEppUpdateClientId is different from current sponsor client // It is possible that the lastEppUpdateRegistrarId is different from current sponsor client
// id, so we have to do the comparison instead of having one variable just storing the most // id, so we have to do the comparison instead of having one variable just storing the most
// recent time. // recent time.
if (newLastEppUpdateTime.isPresent()) { if (newLastEppUpdateTime.isPresent()) {
@ -656,7 +651,7 @@ public class DomainBase extends EppResource
if (includeRegistrant) { if (includeRegistrant) {
registrantContact = null; registrantContact = null;
} }
HashSet<DesignatedContact.Type> contactsDiscovered = new HashSet<DesignatedContact.Type>(); HashSet<DesignatedContact.Type> contactsDiscovered = new HashSet<>();
for (DesignatedContact contact : contacts) { for (DesignatedContact contact : contacts) {
checkArgument( checkArgument(
!contactsDiscovered.contains(contact.getType()), !contactsDiscovered.contains(contact.getType()),
@ -851,17 +846,17 @@ public class DomainBase extends EppResource
return thisCastToDerived(); return thisCastToDerived();
} }
public B setDeletePollMessage(VKey<PollMessage.OneTime> deletePollMessage) { public B setDeletePollMessage(VKey<OneTime> deletePollMessage) {
getInstance().deletePollMessage = deletePollMessage; getInstance().deletePollMessage = deletePollMessage;
return thisCastToDerived(); return thisCastToDerived();
} }
public B setAutorenewBillingEvent(VKey<BillingEvent.Recurring> autorenewBillingEvent) { public B setAutorenewBillingEvent(VKey<Recurring> autorenewBillingEvent) {
getInstance().autorenewBillingEvent = autorenewBillingEvent; getInstance().autorenewBillingEvent = autorenewBillingEvent;
return thisCastToDerived(); return thisCastToDerived();
} }
public B setAutorenewPollMessage(@Nullable VKey<PollMessage.Autorenew> autorenewPollMessage) { public B setAutorenewPollMessage(@Nullable VKey<Autorenew> autorenewPollMessage) {
getInstance().autorenewPollMessage = autorenewPollMessage; getInstance().autorenewPollMessage = autorenewPollMessage;
return thisCastToDerived(); return thisCastToDerived();
} }
@ -931,7 +926,7 @@ public class DomainBase extends EppResource
new IllegalArgumentException( new IllegalArgumentException(
String.format( String.format(
"The package token %s does not exist", "The package token %s does not exist",
currentPackageToken.getSqlKey()))); currentPackageToken.getKey())));
checkArgument( checkArgument(
token.getTokenType().equals(TokenType.PACKAGE), token.getTokenType().equals(TokenType.PACKAGE),
"The currentPackageToken must have a PACKAGE TokenType"); "The currentPackageToken must have a PACKAGE TokenType");

View file

@ -186,7 +186,7 @@ public class DomainHistory extends HistoryEntry {
/** Creates a {@link VKey} instance for this entity. */ /** Creates a {@link VKey} instance for this entity. */
@Override @Override
public VKey<DomainHistory> createVKey() { public VKey<DomainHistory> createVKey() {
return VKey.createSql(DomainHistory.class, getHistoryEntryId()); return VKey.create(DomainHistory.class, getHistoryEntryId());
} }
@Override @Override

View file

@ -39,10 +39,10 @@ import org.joda.time.DateTime;
"contacts", "contacts",
"nameservers", "nameservers",
"subordinateHosts", "subordinateHosts",
"currentSponsorClientId", "currentSponsorRegistrarId",
"creationClientId", "creationRegistrarId",
"creationTime", "creationTime",
"lastEppUpdateClientId", "lastEppUpdateRegistrarId",
"lastEppUpdateTime", "lastEppUpdateTime",
"registrationExpirationTime", "registrationExpirationTime",
"lastTransferTime", "lastTransferTime",
@ -79,11 +79,11 @@ public abstract class DomainInfoData implements ResponseData {
abstract ImmutableSet<String> getSubordinateHosts(); abstract ImmutableSet<String> getSubordinateHosts();
@XmlElement(name = "clID") @XmlElement(name = "clID")
abstract String getCurrentSponsorClientId(); abstract String getCurrentSponsorRegistrarId();
@XmlElement(name = "crID") @XmlElement(name = "crID")
@Nullable @Nullable
abstract String getCreationClientId(); abstract String getCreationRegistrarId();
@XmlElement(name = "crDate") @XmlElement(name = "crDate")
@Nullable @Nullable
@ -91,7 +91,7 @@ public abstract class DomainInfoData implements ResponseData {
@XmlElement(name = "upID") @XmlElement(name = "upID")
@Nullable @Nullable
abstract String getLastEppUpdateClientId(); abstract String getLastEppUpdateRegistrarId();
@XmlElement(name = "upDate") @XmlElement(name = "upDate")
@Nullable @Nullable
@ -121,10 +121,15 @@ public abstract class DomainInfoData implements ResponseData {
@Nullable ImmutableSet<ForeignKeyedDesignatedContact> contacts); @Nullable ImmutableSet<ForeignKeyedDesignatedContact> contacts);
public abstract Builder setNameservers(@Nullable ImmutableSet<String> nameservers); public abstract Builder setNameservers(@Nullable ImmutableSet<String> nameservers);
public abstract Builder setSubordinateHosts(@Nullable ImmutableSet<String> subordinateHosts); public abstract Builder setSubordinateHosts(@Nullable ImmutableSet<String> subordinateHosts);
public abstract Builder setCurrentSponsorClientId(String currentSponsorClientId);
public abstract Builder setCreationClientId(@Nullable String creationClientId); public abstract Builder setCurrentSponsorRegistrarId(String currentSponsorRegistrarId);
public abstract Builder setCreationRegistrarId(@Nullable String creationRegistrarId);
public abstract Builder setCreationTime(@Nullable DateTime creationTime); public abstract Builder setCreationTime(@Nullable DateTime creationTime);
public abstract Builder setLastEppUpdateClientId(@Nullable String lastEppUpdateClientId);
public abstract Builder setLastEppUpdateRegistrarId(@Nullable String lastEppUpdateRegistrarId);
public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime); public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime);
public abstract Builder setRegistrationExpirationTime( public abstract Builder setRegistrationExpirationTime(
@Nullable DateTime registrationExpirationTime); @Nullable DateTime registrationExpirationTime);

View file

@ -38,7 +38,7 @@ public class PackageTokenResponseExtension extends ImmutableObject implements Re
PackageTokenResponseExtension instance = new PackageTokenResponseExtension(); PackageTokenResponseExtension instance = new PackageTokenResponseExtension();
instance.token = ""; instance.token = "";
if (tokenKey.isPresent()) { if (tokenKey.isPresent()) {
instance.token = tokenKey.get().getSqlKey().toString(); instance.token = tokenKey.get().getKey().toString();
} }
return instance; return instance;
} }

View file

@ -273,7 +273,7 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("%s tokens are not stored in the database", getTokenBehavior())); String.format("%s tokens are not stored in the database", getTokenBehavior()));
} }
return VKey.createSql(AllocationToken.class, getToken()); return VKey.create(AllocationToken.class, getToken());
} }
@Override @Override

View file

@ -104,14 +104,14 @@ public class PackagePromotion extends ImmutableObject implements Buildable {
jpaTm().assertInTransaction(); jpaTm().assertInTransaction();
return jpaTm() return jpaTm()
.query("FROM PackagePromotion WHERE token = :token", PackagePromotion.class) .query("FROM PackagePromotion WHERE token = :token", PackagePromotion.class)
.setParameter("token", VKey.createSql(AllocationToken.class, tokenString)) .setParameter("token", VKey.create(AllocationToken.class, tokenString))
.getResultStream() .getResultStream()
.findFirst(); .findFirst();
} }
@Override @Override
public VKey<PackagePromotion> createVKey() { public VKey<PackagePromotion> createVKey() {
return VKey.createSql(PackagePromotion.class, packagePromotionId); return VKey.create(PackagePromotion.class, packagePromotionId);
} }
@Override @Override

View file

@ -64,7 +64,7 @@ public class Host extends HostBase implements ForeignKeyedEppResource {
@Override @Override
public VKey<Host> createVKey() { public VKey<Host> createVKey() {
return VKey.createSql(Host.class, getRepoId()); return VKey.create(Host.class, getRepoId());
} }
@Override @Override

View file

@ -22,9 +22,6 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DomainNameUtils.canonicalizeHostname; import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.condition.IfNull;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.domain.Domain; import google.registry.model.domain.Domain;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
@ -63,14 +60,12 @@ public class HostBase extends EppResource {
* from (creationTime, deletionTime) there can only be one host in Datastore with this name. * from (creationTime, deletionTime) there can only be one host in Datastore with this name.
* However, there can be many hosts with the same name and non-overlapping lifetimes. * However, there can be many hosts with the same name and non-overlapping lifetimes.
*/ */
@Index String hostName; String hostName;
/** IP Addresses for this host. Can be null if this is an external host. */ /** IP Addresses for this host. Can be null if this is an external host. */
@Index Set<InetAddress> inetAddresses; Set<InetAddress> inetAddresses;
/** The superordinate domain of this host, or null if this is an external host. */ /** The superordinate domain of this host, or null if this is an external host. */
@Index
@IgnoreSave(IfNull.class)
@DoNotHydrate @DoNotHydrate
VKey<Domain> superordinateDomain; VKey<Domain> superordinateDomain;
@ -144,7 +139,8 @@ public class HostBase extends EppResource {
* superordinate was transferred. If the last superordinate change was before this time, then the * superordinate was transferred. If the last superordinate change was before this time, then the
* host was attached to this superordinate domain during that transfer. * host was attached to this superordinate domain during that transfer.
* *
* <p>If the host is not subordinate the domain can be null and we just return last transfer time. * <p>If the host is not subordinate the domain can be null, and we just return last transfer
* time.
* *
* @param superordinateDomain the loaded superordinate domain, which must match the key in the * @param superordinateDomain the loaded superordinate domain, which must match the key in the
* {@link #superordinateDomain} field. Passing it as a parameter allows the caller to control * {@link #superordinateDomain} field. Passing it as a parameter allows the caller to control

View file

@ -66,7 +66,7 @@ public class HostHistory extends HistoryEntry {
/** Creates a {@link VKey} instance for this entity. */ /** Creates a {@link VKey} instance for this entity. */
@Override @Override
public VKey<HostHistory> createVKey() { public VKey<HostHistory> createVKey() {
return VKey.createSql(HostHistory.class, getHistoryEntryId()); return VKey.create(HostHistory.class, getHistoryEntryId());
} }
@Override @Override

View file

@ -34,10 +34,10 @@ import org.joda.time.DateTime;
"repoId", "repoId",
"statusValues", "statusValues",
"inetAddresses", "inetAddresses",
"currentSponsorClientId", "currentSponsorRegistrarId",
"creationClientId", "creationRegistrarId",
"creationTime", "creationTime",
"lastEppUpdateClientId", "lastEppUpdateRegistrarId",
"lastEppUpdateTime", "lastEppUpdateTime",
"lastTransferTime" "lastTransferTime"
}) })
@ -58,17 +58,17 @@ public abstract class HostInfoData implements ResponseData {
abstract ImmutableSet<InetAddress> getInetAddresses(); abstract ImmutableSet<InetAddress> getInetAddresses();
@XmlElement(name = "clID") @XmlElement(name = "clID")
abstract String getCurrentSponsorClientId(); abstract String getCurrentSponsorRegistrarId();
@XmlElement(name = "crID") @XmlElement(name = "crID")
abstract String getCreationClientId(); abstract String getCreationRegistrarId();
@XmlElement(name = "crDate") @XmlElement(name = "crDate")
abstract DateTime getCreationTime(); abstract DateTime getCreationTime();
@XmlElement(name = "upID") @XmlElement(name = "upID")
@Nullable @Nullable
abstract String getLastEppUpdateClientId(); abstract String getLastEppUpdateRegistrarId();
@XmlElement(name = "upDate") @XmlElement(name = "upDate")
@Nullable @Nullable
@ -86,10 +86,15 @@ public abstract class HostInfoData implements ResponseData {
public abstract Builder setRepoId(String repoId); public abstract Builder setRepoId(String repoId);
public abstract Builder setStatusValues(ImmutableSet<StatusValue> statusValues); public abstract Builder setStatusValues(ImmutableSet<StatusValue> statusValues);
public abstract Builder setInetAddresses(ImmutableSet<InetAddress> inetAddresses); public abstract Builder setInetAddresses(ImmutableSet<InetAddress> inetAddresses);
public abstract Builder setCurrentSponsorClientId(String currentSponsorClientId);
public abstract Builder setCreationClientId(String creationClientId); public abstract Builder setCurrentSponsorRegistrarId(String currentSponsorRegistrarId);
public abstract Builder setCreationRegistrarId(String creationRegistrarId);
public abstract Builder setCreationTime(DateTime creationTime); public abstract Builder setCreationTime(DateTime creationTime);
public abstract Builder setLastEppUpdateClientId(@Nullable String lastEppUpdateClientId);
public abstract Builder setLastEppUpdateRegistrarId(@Nullable String lastEppUpdateRegistrarId);
public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime); public abstract Builder setLastEppUpdateTime(@Nullable DateTime lastEppUpdateTime);
public abstract Builder setLastTransferTime(@Nullable DateTime lastTransferTime); public abstract Builder setLastTransferTime(@Nullable DateTime lastTransferTime);
public abstract HostInfoData build(); public abstract HostInfoData build();

View file

@ -33,16 +33,15 @@ import com.googlecode.objectify.impl.translate.TranslatorFactory;
import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory; import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory;
import google.registry.config.RegistryEnvironment; import google.registry.config.RegistryEnvironment;
import google.registry.model.Buildable; import google.registry.model.Buildable;
import google.registry.model.EntityClasses;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration; import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.GaeUserIdConverter;
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory; import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
import google.registry.model.translators.CidrAddressBlockTranslatorFactory; import google.registry.model.translators.CidrAddressBlockTranslatorFactory;
import google.registry.model.translators.CurrencyUnitTranslatorFactory; import google.registry.model.translators.CurrencyUnitTranslatorFactory;
import google.registry.model.translators.DurationTranslatorFactory; import google.registry.model.translators.DurationTranslatorFactory;
import google.registry.model.translators.InetAddressTranslatorFactory; import google.registry.model.translators.InetAddressTranslatorFactory;
import google.registry.model.translators.ReadableInstantUtcTranslatorFactory; import google.registry.model.translators.ReadableInstantUtcTranslatorFactory;
import google.registry.model.translators.VKeyTranslatorFactory;
/** /**
* An instance of Ofy, obtained via {@code #auditedOfy()}, should be used to access all persistable * An instance of Ofy, obtained via {@code #auditedOfy()}, should be used to access all persistable
@ -106,7 +105,7 @@ public class ObjectifyService {
// Translators must be registered before any entities can be registered. // Translators must be registered before any entities can be registered.
registerTranslators(); registerTranslators();
registerEntityClasses(EntityClasses.ALL_CLASSES); registerEntityClasses(ImmutableSet.of(GaeUserIdConverter.class));
} }
/** Register translators that allow less common types to be stored directly in Datastore. */ /** Register translators that allow less common types to be stored directly in Datastore. */
@ -119,8 +118,7 @@ public class ObjectifyService {
new DurationTranslatorFactory(), new DurationTranslatorFactory(),
new InetAddressTranslatorFactory(), new InetAddressTranslatorFactory(),
new MoneyStringTranslatorFactory(), new MoneyStringTranslatorFactory(),
new ReadableInstantUtcTranslatorFactory(), new ReadableInstantUtcTranslatorFactory())) {
new VKeyTranslatorFactory())) {
factory().getTranslators().add(translatorFactory); factory().getTranslators().add(translatorFactory);
} }
} }

View file

@ -398,7 +398,7 @@ public abstract class PollMessage extends ImmutableObject
@Override @Override
public VKey<OneTime> createVKey() { public VKey<OneTime> createVKey() {
return VKey.createSql(OneTime.class, getId()); return VKey.create(OneTime.class, getId());
} }
@Override @Override
@ -563,7 +563,7 @@ public abstract class PollMessage extends ImmutableObject
@Override @Override
public VKey<Autorenew> createVKey() { public VKey<Autorenew> createVKey() {
return VKey.createSql(Autorenew.class, getId()); return VKey.create(Autorenew.class, getId());
} }
@Override @Override

View file

@ -61,7 +61,7 @@ public final class PollMessageExternalKeyConverter {
} }
try { try {
Long id = Long.parseLong(idComponents.get(0)); Long id = Long.parseLong(idComponents.get(0));
return VKey.createSql(PollMessage.class, id); return VKey.create(PollMessage.class, id);
// Note that idComponents.get(1) is entirely ignored; we never use the year field internally. // Note that idComponents.get(1) is entirely ignored; we never use the year field internally.
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new PollMessageExternalKeyParseException(); throw new PollMessageExternalKeyParseException();

View file

@ -85,7 +85,7 @@ public final class RdeRevision extends UpdateAutoTimestampEntity {
public static int getNextRevision(String tld, DateTime date, RdeMode mode) { public static int getNextRevision(String tld, DateTime date, RdeMode mode) {
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode); RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
Optional<RdeRevision> revisionOptional = Optional<RdeRevision> revisionOptional =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey))); tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey)));
return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0); return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0);
} }
@ -112,7 +112,7 @@ public final class RdeRevision extends UpdateAutoTimestampEntity {
tm().assertInTransaction(); tm().assertInTransaction();
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode); RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
Optional<RdeRevision> revisionOptional = Optional<RdeRevision> revisionOptional =
tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey)); tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey));
if (revision == 0) { if (revision == 0) {
revisionOptional.ifPresent( revisionOptional.ifPresent(
rdeRevision -> { rdeRevision -> {

View file

@ -656,7 +656,7 @@ public class Registrar extends UpdateAutoTimestampEntity implements Buildable, J
/** Creates a {@link VKey} for the given {@code registrarId}. */ /** Creates a {@link VKey} for the given {@code registrarId}. */
public static VKey<Registrar> createVKey(String registrarId) { public static VKey<Registrar> createVKey(String registrarId) {
checkArgumentNotNull(registrarId, "registrarId must be specified"); checkArgumentNotNull(registrarId, "registrarId must be specified");
return VKey.createSql(Registrar.class, registrarId); return VKey.create(Registrar.class, registrarId);
} }
/** A builder for constructing {@link Registrar}, since it is immutable. */ /** A builder for constructing {@link Registrar}, since it is immutable. */

View file

@ -319,7 +319,7 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe
@Override @Override
public VKey<RegistrarPoc> createVKey() { public VKey<RegistrarPoc> createVKey() {
return VKey.createSql(RegistrarPoc.class, new RegistrarPocId(emailAddress, registrarId)); return VKey.create(RegistrarPoc.class, new RegistrarPocId(emailAddress, registrarId));
} }
/** Class to represent the composite primary key for {@link RegistrarPoc} entity. */ /** Class to represent the composite primary key for {@link RegistrarPoc} entity. */

View file

@ -149,7 +149,7 @@ public class HistoryEntryDao {
CriteriaQueryBuilder.create(historyClass) CriteriaQueryBuilder.create(historyClass)
.where("modificationTime", criteriaBuilder::greaterThanOrEqualTo, afterTime) .where("modificationTime", criteriaBuilder::greaterThanOrEqualTo, afterTime)
.where("modificationTime", criteriaBuilder::lessThanOrEqualTo, beforeTime) .where("modificationTime", criteriaBuilder::lessThanOrEqualTo, beforeTime)
.where("repoId", criteriaBuilder::equal, resourceKey.getSqlKey().toString()) .where("repoId", criteriaBuilder::equal, resourceKey.getKey().toString())
.orderByAsc("revisionId") .orderByAsc("revisionId")
.orderByAsc("modificationTime") .orderByAsc("modificationTime")
.build(); .build();

View file

@ -217,7 +217,7 @@ public class Lock extends ImmutableObject implements Serializable {
// Checking if an unexpired lock still exists - if so, the lock can't be acquired. // Checking if an unexpired lock still exists - if so, the lock can't be acquired.
Lock lock = Lock lock =
jpaTm() jpaTm()
.loadByKeyIfPresent(VKey.createSql(Lock.class, new LockId(resourceName, scope))) .loadByKeyIfPresent(VKey.create(Lock.class, new LockId(resourceName, scope)))
.orElse(null); .orElse(null);
if (lock != null) { if (lock != null) {
logger.atInfo().log( logger.atInfo().log(
@ -257,7 +257,7 @@ public class Lock extends ImmutableObject implements Serializable {
// delete it. If the lock in the database was different, then this lock is gone already; // delete it. If the lock in the database was different, then this lock is gone already;
// this can happen if release() is called around the expiration time and the lock // this can happen if release() is called around the expiration time and the lock
// expires underneath us. // expires underneath us.
VKey<Lock> key = VKey.createSql(Lock.class, new LockId(resourceName, scope)); VKey<Lock> key = VKey.create(Lock.class, new LockId(resourceName, scope));
Lock loadedLock = jpaTm().loadByKeyIfPresent(key).orElse(null); Lock loadedLock = jpaTm().loadByKeyIfPresent(key).orElse(null);
if (equals(loadedLock)) { if (equals(loadedLock)) {
// Use deleteIgnoringReadOnly() so that we don't create a commit log entry for deleting // Use deleteIgnoringReadOnly() so that we don't create a commit log entry for deleting

View file

@ -210,12 +210,12 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
}); });
public static VKey<Registry> createVKey(String tld) { public static VKey<Registry> createVKey(String tld) {
return VKey.createSql(Registry.class, tld); return VKey.create(Registry.class, tld);
} }
@Override @Override
public VKey<Registry> createVKey() { public VKey<Registry> createVKey() {
return VKey.createSql(Registry.class, tldStr); return VKey.create(Registry.class, tldStr);
} }
/** /**

View file

@ -88,9 +88,9 @@ public abstract class TransferData extends BaseTransferObject implements Buildab
public ImmutableSet<VKey<? extends TransferServerApproveEntity>> getServerApproveEntities() { public ImmutableSet<VKey<? extends TransferServerApproveEntity>> getServerApproveEntities() {
return NullIgnoringCollectionBuilder.create( return NullIgnoringCollectionBuilder.create(
new ImmutableSet.Builder<VKey<? extends TransferServerApproveEntity>>()) new ImmutableSet.Builder<VKey<? extends TransferServerApproveEntity>>())
.add(pollMessageId1 != null ? VKey.createSql(PollMessage.class, pollMessageId1) : null) .add(pollMessageId1 != null ? VKey.create(PollMessage.class, pollMessageId1) : null)
.add(pollMessageId2 != null ? VKey.createSql(PollMessage.class, pollMessageId2) : null) .add(pollMessageId2 != null ? VKey.create(PollMessage.class, pollMessageId2) : null)
.add(pollMessageId3 != null ? VKey.createSql(PollMessage.class, pollMessageId3) : null) .add(pollMessageId3 != null ? VKey.create(PollMessage.class, pollMessageId3) : null)
.getBuilder() .getBuilder()
.build(); .build();
} }
@ -153,7 +153,7 @@ public abstract class TransferData extends BaseTransferObject implements Buildab
Set<VKey<? extends TransferServerApproveEntity>> serverApproveEntities) { Set<VKey<? extends TransferServerApproveEntity>> serverApproveEntities) {
return nullToEmpty(serverApproveEntities).stream() return nullToEmpty(serverApproveEntities).stream()
.filter(vKey -> PollMessage.class.isAssignableFrom(vKey.getKind())) .filter(vKey -> PollMessage.class.isAssignableFrom(vKey.getKind()))
.map(vKey -> (long) vKey.getSqlKey()) .map(vKey -> (long) vKey.getKey())
.sorted() .sorted()
.collect(toImmutableList()); .collect(toImmutableList());
} }

View file

@ -1,98 +0,0 @@
// 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.model.translators;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.appengine.api.datastore.Key;
import google.registry.model.common.ClassPathManager;
import google.registry.persistence.VKey;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nullable;
/**
* Translator factory for VKey.
*
* <p>These get translated to a string containing the URL safe encoding of the objectify key
* followed by a (url-unsafe) ampersand delimiter and the SQL key.
*/
public class VKeyTranslatorFactory extends AbstractSimpleTranslatorFactory<VKey, Key> {
public VKeyTranslatorFactory() {
super(VKey.class);
}
/** Create a VKey from a raw datastore key. */
@Nullable
public static VKey<?> createVKey(@Nullable Key datastoreKey) {
if (datastoreKey == null) {
return null;
}
return createVKey(com.googlecode.objectify.Key.create(datastoreKey));
}
/** Create a VKey from an objectify Key. */
@Nullable
@SuppressWarnings("unchecked")
public static <T> VKey<T> createVKey(@Nullable com.googlecode.objectify.Key<T> key) {
if (key == null) {
return null;
}
// Try to create the VKey from its reference type.
Class<T> clazz = ClassPathManager.getClass(key.getKind());
checkArgument(clazz != null, "Unknown Key type: %s", key.getKind());
try {
Method createVKeyMethod =
clazz.getDeclaredMethod("createVKey", com.googlecode.objectify.Key.class);
return (VKey<T>) createVKeyMethod.invoke(null, new Object[] {key});
} catch (NoSuchMethodException e) {
checkArgument(
key.getParent() == null,
"Cannot auto-convert key %s of kind %s because it has a parent. Add a createVKey(Key) "
+ "method for it.",
key,
key.getKind());
if (key.getName() != null) {
return VKey.create(clazz, key.getName(), key);
} else {
return VKey.create(clazz, key.getId(), key);
}
} catch (IllegalAccessException | InvocationTargetException e) {
// If we have a createVKey(Key) method with incorrect permissions or that is non-static, this
// is probably an error so let's reported.
throw new RuntimeException(e);
}
}
@Override
public SimpleTranslator<VKey, Key> createTranslator() {
return new SimpleTranslator<VKey, Key>() {
@Nullable
@Override
public VKey loadValue(@Nullable Key datastoreValue) {
return createVKey(datastoreValue);
}
@Nullable
@Override
public Key saveValue(@Nullable VKey key) {
return key == null ? null : key.getOfyKey().getRaw();
}
};
}
}

View file

@ -14,236 +14,89 @@
package google.registry.persistence; package google.registry.persistence;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.util.function.Function.identity;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Key; import google.registry.model.EppResource;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.UpdateAutoTimestampEntity; import google.registry.model.contact.Contact;
import google.registry.model.common.ClassPathManager; import google.registry.model.domain.Domain;
import google.registry.model.translators.VKeyTranslatorFactory; import google.registry.model.host.Host;
import google.registry.util.SerializeUtils; import google.registry.util.SerializeUtils;
import java.io.Serializable; import java.io.Serializable;
import java.util.Optional;
import javax.annotation.Nullable;
/** /**
* VKey is an abstraction that encapsulates the key concept. * VKey is an abstraction that encapsulates the key concept.
* *
* <p>A VKey instance must contain both the JPA primary key for the referenced entity class and the * <p>A VKey instance must contain the JPA primary key for the referenced entity class.
* objectify key for the object.
*/ */
public class VKey<T> extends ImmutableObject implements Serializable { public class VKey<T> extends ImmutableObject implements Serializable {
private static final long serialVersionUID = -5291472863840231240L; private static final long serialVersionUID = -5291472863840231240L;
// Info that's stored in in vkey string generated via stringify(). // Info that's stored in VKey string generated via stringify().
private static final String SQL_LOOKUP_KEY = "sql"; private static final String LOOKUP_KEY = "sql";
private static final String OFY_LOOKUP_KEY = "ofy";
private static final String CLASS_TYPE = "kind"; private static final String CLASS_TYPE = "kind";
// Web safe delimiters that won't be used in base 64. // Web safe delimiters that won't be used in base 64.
private static final String KV_SEPARATOR = ":"; private static final String KV_SEPARATOR = ":";
private static final String DELIMITER = "@"; private static final String DELIMITER = "@";
// The SQL key for the referenced entity. private static final ImmutableMap<String, Class<? extends EppResource>> EPP_RESOURCE_CLASS_MAP =
Serializable sqlKey; ImmutableList.of(Domain.class, Host.class, Contact.class).stream()
.collect(toImmutableMap(Class::getSimpleName, identity()));
// The objectify key for the referenced entity. Marked Insignificant to exclude it from // The primary key for the referenced entity.
// hashing/equality. Serializable key;
@Insignificant Key<T> ofyKey;
Class<? extends T> kind; Class<? extends T> kind;
@SuppressWarnings("unused")
VKey() {} VKey() {}
VKey(Class<? extends T> kind, Key<T> ofyKey, Serializable sqlKey) { VKey(Class<? extends T> kind, Serializable key) {
this.kind = kind; this.kind = kind;
this.ofyKey = ofyKey; this.key = key;
this.sqlKey = sqlKey;
} }
/** /** Creates a {@link VKey} with supplied the SQL primary key. */
* Creates a {@link VKey} which only contains the sql primary key. public static <T> VKey<T> create(Class<T> kind, Serializable key) {
*
* <p>Deprecated. Create symmetric keys with create() instead.
*/
public static <T> VKey<T> createSql(Class<T> kind, Serializable sqlKey) {
checkArgumentNotNull(kind, "kind must not be null"); checkArgumentNotNull(kind, "kind must not be null");
checkArgumentNotNull(sqlKey, "sqlKey must not be null"); checkArgumentNotNull(key, "key must not be null");
return new VKey<T>(kind, null, sqlKey); return new VKey<>(kind, key);
}
/** Creates a {@link VKey} which only contains the ofy primary key. */
public static <T> VKey<T> createOfy(Class<? extends T> kind, Key<T> ofyKey) {
checkArgumentNotNull(kind, "kind must not be null");
checkArgumentNotNull(ofyKey, "ofyKey must not be null");
return new VKey<T>(kind, ofyKey, null);
}
/** Creates a {@link VKey} which only contains both sql and ofy primary key. */
public static <T> VKey<T> create(Class<T> kind, Serializable sqlKey, Key<T> 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<T>(kind, ofyKey, sqlKey);
} }
/** /**
* Creates a symmetric {@link VKey} in which both sql and ofy keys are {@code id}. * Constructs a {@link VKey} for an {@link EppResource } from the string representation.
* *
* <p>IMPORTANT USAGE NOTE: Datastore entities that are not roots of entity groups (i.e. those * <p>The string representation is obtained from the {@link #stringify()} function and like this:
* that do not have a null parent in their Objectify keys) require the full entity group * {@code kind:TestObject@sql:rO0ABXQAA2Zvbw}
* inheritance chain to be specified and thus cannot use this create method. You need to use
* {@link #create(Class, Serializable, Key)} instead and pass in the full, valid parent field in
* the Datastore key.
*/ */
public static <T> VKey<T> create(Class<T> kind, long id) { public static <T extends EppResource> VKey<T> createEppVKeyFromString(String keyString) {
checkArgument(
UpdateAutoTimestampEntity.class.isAssignableFrom(kind),
"The kind %s is not a UpdateAutoTimestampEntity and thus needs its entire entity group"
+ " chain specified in a parent",
kind.getCanonicalName());
return new VKey<T>(kind, Key.create(kind, id), id);
}
/**
* Creates a symmetric {@link VKey} in which both sql and ofy keys are {@code name}.
*
* <p>IMPORTANT USAGE NOTE: Datastore entities that are not roots of entity groups (i.e. those
* that do not have a null parent in their Objectify keys) require the full entity group
* inheritance chain to be specified and thus cannot use this create method. You need to use
* {@link #create(Class, Serializable, Key)} instead and pass in the full, valid parent field in
* the Datastore key.
*/
public static <T> VKey<T> create(Class<T> kind, String name) {
checkArgument(
UpdateAutoTimestampEntity.class.isAssignableFrom(kind),
"The kind %s is not a UpdateAutoTimestampEntity and thus needs its entire entity group"
+ " chain specified in a parent",
kind.getCanonicalName());
return new VKey<T>(kind, Key.create(kind, name), name);
}
/**
* Constructs a {@link VKey} from the string representation of a vkey.
*
* <p>There are two types of string representations: 1) existing ofy key string handled by
* fromWebsafeKey() and 2) string encoded via stringify() where @ separates the substrings and
* each of the substrings contains a look up key, ":", and its corresponding value. The key info
* is encoded via Base64. The string begins with "kind:" and it must contains at least ofy key or
* sql key.
*
* <p>Example of a Vkey string by fromWebsafeKey(): "agR0ZXN0chYLEgpEb21haW5CYXNlIgZST0lELTEM"
*
* <p>Example of a vkey string by stringify(): "kind:TestObject@sql:rO0ABXQAA2Zvbw" +
* "@ofy:agR0ZXN0cjELEg9FbnRpdHlHcm91cFJvb3QiCWNyb3NzLXRsZAwLEgpUZXN0T2JqZWN0IgNmb28M", where sql
* key and ofy key values are encoded in Base64.
*/
public static <T> VKey<T> create(String keyString) {
if (!keyString.startsWith(CLASS_TYPE + KV_SEPARATOR)) {
// handle the existing ofy key string
return fromWebsafeKey(keyString);
} else {
ImmutableMap<String, String> kvs = ImmutableMap<String, String> kvs =
ImmutableMap.copyOf( ImmutableMap.copyOf(
Splitter.on(DELIMITER).withKeyValueSeparator(KV_SEPARATOR).split(keyString)); Splitter.on(DELIMITER).withKeyValueSeparator(KV_SEPARATOR).split(keyString));
Class classType = ClassPathManager.getClass(kvs.get(CLASS_TYPE)); String classString = kvs.get(CLASS_TYPE);
if (classString == null) {
if (kvs.containsKey(SQL_LOOKUP_KEY) && kvs.containsKey(OFY_LOOKUP_KEY)) {
return VKey.create(
classType,
SerializeUtils.parse(Serializable.class, kvs.get(SQL_LOOKUP_KEY)),
Key.create(kvs.get(OFY_LOOKUP_KEY)));
} else if (kvs.containsKey(SQL_LOOKUP_KEY)) {
return VKey.createSql(
classType, SerializeUtils.parse(Serializable.class, kvs.get(SQL_LOOKUP_KEY)));
} else if (kvs.containsKey(OFY_LOOKUP_KEY)) {
return VKey.createOfy(classType, Key.create(kvs.get(OFY_LOOKUP_KEY)));
} else {
throw new IllegalArgumentException(String.format("Cannot parse key string: %s", keyString));
}
}
}
/**
* Returns a clone with an ofy key restored from {@code ancestors}.
*
* <p>The arguments should generally consist of pairs of Class and value, where the Class is the
* kind of the ancestor key and the value is either a String or a Long.
*
* <p>For example, to restore the objectify key for
* Domain("COM-1234")/HistoryEntry(123)/PollEvent(567), one might use:
*
* <pre>{@code
* pollEvent.restoreOfy(Domain.class, "COM-1234", HistoryEntry.class, 567)
* }</pre>
*
* <p>The final key id or name is obtained from the SQL key. It is assumed that this value must be
* either a long integer or a {@code String} and that this proper identifier for the objectify
* key.
*
* <p>As a special case, an objectify Key may be used as the first ancestor instead of a Class,
* value pair.
*/
public VKey<T> restoreOfy(Object... ancestors) {
Class lastClass = null;
Key<?> lastKey = null;
for (Object ancestor : ancestors) {
if (ancestor instanceof Class) {
if (lastClass != null) {
throw new IllegalArgumentException(ancestor + " used as a key value.");
}
lastClass = (Class) ancestor;
continue;
} else if (ancestor instanceof Key) {
if (lastKey != null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Objectify keys may only be used for the first argument"); String.format("\"%s\" missing from the string: %s", CLASS_TYPE, keyString));
} }
lastKey = (Key) ancestor; @SuppressWarnings("unchecked")
continue; Class<T> classType = (Class<T>) EPP_RESOURCE_CLASS_MAP.get(classString);
if (classType == null) {
throw new IllegalArgumentException(String.format("%s is not an EppResource", classString));
} }
String encodedString = kvs.get(LOOKUP_KEY);
// The argument should be a value. if (encodedString == null) {
if (lastClass == null) { throw new IllegalArgumentException(
throw new IllegalArgumentException("Argument " + ancestor + " should be a class."); String.format("\"%s\" missing from the string: %s", LOOKUP_KEY, keyString));
} }
if (ancestor instanceof Long) { return VKey.create(classType, SerializeUtils.parse(Serializable.class, kvs.get(LOOKUP_KEY)));
lastKey = Key.create(lastKey, lastClass, (Long) ancestor);
} else if (ancestor instanceof String) {
lastKey = Key.create(lastKey, lastClass, (String) ancestor);
} else {
throw new IllegalArgumentException("Key value " + ancestor + " must be a string or long.");
}
lastClass = null;
}
// Make sure we didn't end up with a dangling class with no value.
if (lastClass != null) {
throw new IllegalArgumentException("Missing value for last key of type " + lastClass);
}
Serializable sqlKey = getSqlKey();
Key<T> ofyKey =
sqlKey instanceof Long
? Key.create(lastKey, getKind(), (Long) sqlKey)
: Key.create(lastKey, getKind(), (String) sqlKey);
return VKey.create((Class<T>) getKind(), sqlKey, ofyKey);
}
/**
* Returns a clone of {@code key} with an ofy key restored from {@code ancestors}.
*
* <p>This is the static form of the method restoreOfy() above. If {@code key} is null, it returns
* null.
*/
public static <T> VKey<T> restoreOfyFrom(@Nullable VKey<T> key, Object... ancestors) {
return key == null ? null : key.restoreOfy(ancestors);
} }
/** Returns the type of the entity. */ /** Returns the type of the entity. */
@ -251,92 +104,27 @@ public class VKey<T> extends ImmutableObject implements Serializable {
return this.kind; return this.kind;
} }
/** Returns the SQL primary key. */ /** Returns the primary key. */
public Serializable getSqlKey() { public Serializable getKey() {
checkState(sqlKey != null, "Attempting obtain a null SQL key."); return this.key;
return this.sqlKey;
}
/** Returns the SQL primary key if it exists. */
public Optional<Object> maybeGetSqlKey() {
return Optional.ofNullable(this.sqlKey);
}
/** Returns the objectify key. */
public Key<T> getOfyKey() {
checkState(ofyKey != null, "Attempting obtain a null Objectify key.");
return this.ofyKey;
}
/** Returns the objectify key if it exists. */
public Optional<Key<T>> maybeGetOfyKey() {
return Optional.ofNullable(this.ofyKey);
}
/** Convenience method to construct a VKey from an objectify Key. */
@Nullable
public static <T> VKey<T> from(Key<T> key) {
return VKeyTranslatorFactory.createVKey(key);
}
/**
* Construct a VKey from the string representation of an ofy key.
*
* <p>TODO(b/184350590): After migration, we'll want remove the ofy key dependency from this.
*/
@Nullable
public static <T> VKey<T> fromWebsafeKey(String ofyKeyRepr) {
return from(Key.create(ofyKeyRepr));
} }
/** /**
* Constructs the string representation of a {@link VKey}. * Constructs the string representation of a {@link VKey}.
* *
* <p>The string representation of a vkey contains its kind, and sql key or ofy key, or both. Each * <p>The string representation contains its kind and Base64 SQL key, in the following format:
* of the keys is first serialized into a byte array then encoded via Base64 into a web safe * {@code kind:class_name@sql:encoded_sqlKey}.
* string.
*
* <p>The string representation of a vkey contains key values pairs separated by delimiter "@".
* Another delimiter ":" is put in between each key and value. The following is the complete
* format of the string: "kind:class_name@sql:encoded_sqlKey@ofy:encoded_ofyKey", where kind is
* required. The string representation may contain an encoded ofy key, or an encoded sql key, or
* both.
*/ */
public String stringify() { public String stringify() {
// class type is required to create a vkey return Joiner.on(DELIMITER)
String key = CLASS_TYPE + KV_SEPARATOR + ClassPathManager.getClassName(getKind()); .join(
if (maybeGetSqlKey().isPresent()) { CLASS_TYPE + KV_SEPARATOR + getKind().getSimpleName(),
key += DELIMITER + SQL_LOOKUP_KEY + KV_SEPARATOR + SerializeUtils.stringify(getSqlKey()); LOOKUP_KEY + KV_SEPARATOR + SerializeUtils.stringify(getKey()));
}
// getString() method returns a Base64 encoded web safe of ofy key
if (maybeGetOfyKey().isPresent()) {
key += DELIMITER + OFY_LOOKUP_KEY + KV_SEPARATOR + getOfyKey().getString();
}
return key;
} }
/** /** Constructs the readable string representation of a {@link VKey}. */
* Constructs the readable string representation of a {@link VKey}.
*
* <p>This readable string representation of a vkey contains its kind and its sql key or ofy key,
* or both.
*/
@Override @Override
public String toString() { public String toString() {
if (maybeGetOfyKey().isPresent() && maybeGetSqlKey().isPresent()) { return String.format("VKey<%s>(%s:%s)", getKind().getSimpleName(), LOOKUP_KEY, key);
return String.format(
"VKey<%s>(%s:%s,%s:%s)",
getKind().getSimpleName(), SQL_LOOKUP_KEY, sqlKey, OFY_LOOKUP_KEY, ofyKeyToString());
} else if (maybeGetSqlKey().isPresent()) {
return String.format("VKey<%s>(%s:%s)", getKind().getSimpleName(), SQL_LOOKUP_KEY, sqlKey);
} else if (maybeGetOfyKey().isPresent()) {
return String.format("VKey<%s>(%s:%s)", ofyKey.getKind(), OFY_LOOKUP_KEY, ofyKeyToString());
} else {
throw new IllegalStateException("VKey should contain at least one form of key");
}
}
private String ofyKeyToString() {
return ofyKey.getName() == null ? String.valueOf(ofyKey.getId()) : ofyKey.getName();
} }
} }

View file

@ -27,11 +27,11 @@ public class TransferServerApproveEntitySetConverter
@Override @Override
String toString(VKey<? extends TransferServerApproveEntity> element) { String toString(VKey<? extends TransferServerApproveEntity> element) {
return String.valueOf(element.getSqlKey()); return String.valueOf(element.getKey());
} }
@Override @Override
VKey<? extends TransferServerApproveEntity> fromString(String value) { VKey<? extends TransferServerApproveEntity> fromString(String value) {
return VKey.createSql(TransferServerApproveEntity.class, Long.parseLong(value)); return VKey.create(TransferServerApproveEntity.class, Long.parseLong(value));
} }
} }

View file

@ -34,12 +34,12 @@ public abstract class VKeyConverter<T, C extends Serializable>
return null; return null;
} }
try { try {
return getKeyClass().cast(attribute.getSqlKey()); return getKeyClass().cast(attribute.getKey());
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new RuntimeException( throw new RuntimeException(
String.format( String.format(
"Cannot cast SQL key %s of type %s to type %s", "Cannot cast SQL key %s of type %s to type %s",
attribute.getSqlKey(), attribute.getSqlKey().getClass(), getKeyClass()), attribute.getKey(), attribute.getKey().getClass(), getKeyClass()),
e); e);
} }
} }
@ -50,7 +50,7 @@ public abstract class VKeyConverter<T, C extends Serializable>
if (dbData == null) { if (dbData == null) {
return null; return null;
} }
return VKey.createSql(getEntityClass(), dbData); return VKey.create(getEntityClass(), dbData);
} }
/** Returns the class of the entity that the VKey represents. */ /** Returns the class of the entity that the VKey represents. */

View file

@ -284,7 +284,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
public <T> boolean exists(VKey<T> key) { public <T> boolean exists(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified"); checkArgumentNotNull(key, "key must be specified");
EntityType<?> entityType = getEntityType(key.getKind()); EntityType<?> entityType = getEntityType(key.getKind());
ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getSqlKey()); ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getKey());
return exists(entityType.getName(), entityIds); return exists(entityType.getName(), entityIds);
} }
@ -311,7 +311,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
public <T> Optional<T> loadByKeyIfPresent(VKey<T> key) { public <T> Optional<T> loadByKeyIfPresent(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified"); checkArgumentNotNull(key, "key must be specified");
assertInTransaction(); assertInTransaction();
return Optional.ofNullable(getEntityManager().find(key.getKind(), key.getSqlKey())) return Optional.ofNullable(getEntityManager().find(key.getKind(), key.getKey()))
.map(this::detach); .map(this::detach);
} }
@ -326,7 +326,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
.map( .map(
key -> key ->
new SimpleEntry<VKey<? extends T>, T>( new SimpleEntry<VKey<? extends T>, T>(
key, detach(getEntityManager().find(key.getKind(), key.getSqlKey())))) key, detach(getEntityManager().find(key.getKind(), key.getKey()))))
.filter(entry -> entry.getValue() != null) .filter(entry -> entry.getValue() != null)
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); .collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
} }
@ -343,7 +343,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
public <T> T loadByKey(VKey<T> key) { public <T> T loadByKey(VKey<T> key) {
checkArgumentNotNull(key, "key must be specified"); checkArgumentNotNull(key, "key must be specified");
assertInTransaction(); assertInTransaction();
T result = getEntityManager().find(key.getKind(), key.getSqlKey()); T result = getEntityManager().find(key.getKind(), key.getKey());
if (result == null) { if (result == null) {
throw new NoSuchElementException(key.toString()); throw new NoSuchElementException(key.toString());
} }
@ -372,7 +372,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
T returnValue = T returnValue =
(T) (T)
loadByKey( loadByKey(
VKey.createSql( VKey.create(
entity.getClass(), entity.getClass(),
// Casting to Serializable is safe according to JPA (JSR 338 sec. 2.4). // Casting to Serializable is safe according to JPA (JSR 338 sec. 2.4).
(Serializable) emf.getPersistenceUnitUtil().getIdentifier(entity))); (Serializable) emf.getPersistenceUnitUtil().getIdentifier(entity)));
@ -418,7 +418,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
checkArgumentNotNull(key, "key must be specified"); checkArgumentNotNull(key, "key must be specified");
assertInTransaction(); assertInTransaction();
EntityType<?> entityType = getEntityType(key.getKind()); EntityType<?> entityType = getEntityType(key.getKind());
ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getSqlKey()); ImmutableSet<EntityId> entityIds = getEntityIdsFromSqlKey(entityType, key.getKey());
String sql = String sql =
String.format("DELETE FROM %s WHERE %s", entityType.getName(), getAndClause(entityIds)); String.format("DELETE FROM %s WHERE %s", entityType.getName(), getAndClause(entityIds));
Query query = query(sql); Query query = query(sql);
@ -460,7 +460,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
public <T> void assertDelete(VKey<T> key) { public <T> void assertDelete(VKey<T> key) {
if (internalDelete(key) != 1) { if (internalDelete(key) != 1) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("Error deleting the entity of the key: %s", key.getSqlKey())); String.format("Error deleting the entity of the key: %s", key.getKey()));
} }
} }

View file

@ -318,7 +318,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
if (desiredRegistrar.isPresent()) { if (desiredRegistrar.isPresent()) {
builder = builder =
builder.where( builder.where(
"currentSponsorClientId", "currentSponsorRegistrarId",
replicaJpaTm().getEntityManager().getCriteriaBuilder()::equal, replicaJpaTm().getEntityManager().getCriteriaBuilder()::equal,
desiredRegistrar.get()); desiredRegistrar.get());
} }

View file

@ -273,7 +273,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
if (!rdapAuthorization.role().equals(Role.ADMINISTRATOR)) { if (!rdapAuthorization.role().equals(Role.ADMINISTRATOR)) {
builder = builder =
builder.whereFieldIsIn( builder.whereFieldIsIn(
"currentSponsorClientId", rdapAuthorization.registrarIds()); "currentSponsorRegistrarId", rdapAuthorization.registrarIds());
} }
return getMatchingResources(builder, false, rdapResultSetMaxSize + 1); return getMatchingResources(builder, false, rdapResultSetMaxSize + 1);
}); });

View file

@ -905,7 +905,7 @@ public class RdapJsonFormatter {
String jpql = String jpql =
GET_LAST_HISTORY_BY_TYPE_JPQL_TEMPLATE GET_LAST_HISTORY_BY_TYPE_JPQL_TEMPLATE
.replace("%entityName%", entityName) .replace("%entityName%", entityName)
.replace("%repoIdValue%", resourceVkey.getSqlKey().toString()); .replace("%repoIdValue%", resourceVkey.getKey().toString());
Iterable<HistoryEntry> historyEntries = Iterable<HistoryEntry> historyEntries =
replicaJpaTm() replicaJpaTm()
.transact( .transact(

View file

@ -163,7 +163,7 @@ public abstract class RdapSearchActionBase extends RdapActionBase {
if (desiredRegistrar.isPresent()) { if (desiredRegistrar.isPresent()) {
builder = builder =
builder.where( builder.where(
"currentSponsorClientId", "currentSponsorRegistrarId",
replicaJpaTm().getEntityManager().getCriteriaBuilder()::equal, replicaJpaTm().getEntityManager().getCriteriaBuilder()::equal,
desiredRegistrar.get()); desiredRegistrar.get());
} }

View file

@ -67,7 +67,7 @@ abstract class CreateOrUpdatePackagePromotionCommand extends MutatingCommand {
/** Returns the allocation token object. */ /** Returns the allocation token object. */
AllocationToken getAndCheckAllocationToken(String token) { AllocationToken getAndCheckAllocationToken(String token) {
Optional<AllocationToken> allocationToken = Optional<AllocationToken> allocationToken =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(AllocationToken.class, token))); tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
checkArgument( checkArgument(
allocationToken.isPresent(), allocationToken.isPresent(),
"An allocation token with the token String %s does not exist. The package token must be" "An allocation token with the token String %s does not exist. The package token must be"

View file

@ -87,8 +87,7 @@ final class DeleteAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
System.out.printf( System.out.printf(
"%s tokens: %s\n", "%s tokens: %s\n",
dryRun ? "Would delete" : "Deleted", dryRun ? "Would delete" : "Deleted",
JOINER.join( JOINER.join(tokensToDelete.stream().map(VKey::getKey).sorted().collect(toImmutableList())));
tokensToDelete.stream().map(VKey::getSqlKey).sorted().collect(toImmutableList())));
return tokensToDelete.size(); return tokensToDelete.size();
} }
} }

View file

@ -314,7 +314,7 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) { private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) {
ImmutableSet<VKey<AllocationToken>> existingTokenKeys = ImmutableSet<VKey<AllocationToken>> existingTokenKeys =
candidates.stream() candidates.stream()
.map(input -> VKey.createSql(AllocationToken.class, input)) .map(input -> VKey.create(AllocationToken.class, input))
.collect(toImmutableSet()); .collect(toImmutableSet());
return tm().transact( return tm().transact(
() -> () ->

View file

@ -47,12 +47,12 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) { for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) {
ImmutableList<VKey<AllocationToken>> tokenKeys = ImmutableList<VKey<AllocationToken>> tokenKeys =
tokens.stream() tokens.stream()
.map(t -> VKey.createSql(AllocationToken.class, t)) .map(t -> VKey.create(AllocationToken.class, t))
.collect(toImmutableList()); .collect(toImmutableList());
tm().transact( tm().transact(
() -> () ->
tm().loadByKeysIfPresent(tokenKeys) tm().loadByKeysIfPresent(tokenKeys)
.forEach((k, v) -> builder.put(k.getSqlKey().toString(), v))); .forEach((k, v) -> builder.put(k.getKey().toString(), v)));
} }
ImmutableMap<String, AllocationToken> loadedTokens = builder.build(); ImmutableMap<String, AllocationToken> loadedTokens = builder.build();
ImmutableMap<VKey<Domain>, Domain> domains = ImmutableMap<VKey<Domain>, Domain> domains =
@ -66,7 +66,7 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
System.out.printf("Token %s was not redeemed.\n", token); System.out.printf("Token %s was not redeemed.\n", token);
} else { } else {
VKey<Domain> domainKey = VKey<Domain> domainKey =
VKey.createSql(Domain.class, loadedToken.getRedemptionHistoryId().get().getRepoId()); VKey.create(Domain.class, loadedToken.getRedemptionHistoryId().get().getRepoId());
Domain domain = domains.get(domainKey); Domain domain = domains.get(domainKey);
if (domain == null) { if (domain == null) {
System.out.printf("ERROR: Token %s was redeemed but domain can't be loaded.\n", token); System.out.printf("ERROR: Token %s was redeemed but domain can't be loaded.\n", token);
@ -91,8 +91,8 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
.map(AllocationToken::getRedemptionHistoryId) .map(AllocationToken::getRedemptionHistoryId)
.filter(Optional::isPresent) .filter(Optional::isPresent)
.map(Optional::get) .map(Optional::get)
.map(hi -> tm().loadByKey(VKey.createSql(DomainHistory.class, hi))) .map(hi -> tm().loadByKey(VKey.create(DomainHistory.class, hi)))
.map(dh -> VKey.createSql(Domain.class, dh.getRepoId())) .map(dh -> VKey.create(Domain.class, dh.getRepoId()))
.collect(toImmutableList()); .collect(toImmutableList());
ImmutableMap.Builder<VKey<Domain>, Domain> domainsBuilder = new ImmutableMap.Builder<>(); ImmutableMap.Builder<VKey<Domain>, Domain> domainsBuilder = new ImmutableMap.Builder<>();
for (List<VKey<Domain>> keys : Lists.partition(domainKeys, BATCH_SIZE)) { for (List<VKey<Domain>> keys : Lists.partition(domainKeys, BATCH_SIZE)) {

View file

@ -1,48 +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.tools;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.model.SchemaVersion;
import google.registry.model.annotations.DeleteAfterMigration;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/** Generates the schema file used for model versioning. */
@DeleteAfterMigration
@Parameters(commandDescription = "Generate a model schema file")
final class GetSchemaCommand implements Command {
@Parameter(
names = {"-o", "--out_file"},
description = "Name of the output file.")
String outFile;
@Override
public void run() throws IOException {
String schema = SchemaVersion.getSchema();
if (outFile == null) {
System.out.println(schema);
} else {
File file = new File(outFile);
file.createNewFile(); // Create the output file if it doesn't already exist.
Files.write(file.toPath(), schema.getBytes(UTF_8));
}
}
}

View file

@ -89,7 +89,7 @@ public abstract class MutatingCommand extends ConfirmingCommand implements Comma
/** Returns a human-readable ID string for the entity being changed. */ /** Returns a human-readable ID string for the entity being changed. */
String getEntityId() { String getEntityId() {
return String.format("%s@%s", vKey.getKind().getSimpleName(), vKey.getSqlKey().toString()); return String.format("%s@%s", vKey.getKind().getSimpleName(), vKey.getKey().toString());
} }
/** Returns a string representation of this entity change. */ /** Returns a string representation of this entity change. */

View file

@ -78,7 +78,6 @@ public final class RegistryTool {
.put("get_registrar", GetRegistrarCommand.class) .put("get_registrar", GetRegistrarCommand.class)
.put("get_reserved_list", GetReservedListCommand.class) .put("get_reserved_list", GetReservedListCommand.class)
.put("get_routing_map", GetRoutingMapCommand.class) .put("get_routing_map", GetRoutingMapCommand.class)
.put("get_schema", GetSchemaCommand.class)
.put("get_sql_credential", GetSqlCredentialCommand.class) .put("get_sql_credential", GetSqlCredentialCommand.class)
.put("get_tld", GetTldCommand.class) .put("get_tld", GetTldCommand.class)
.put("ghostryde", GhostrydeCommand.class) .put("ghostryde", GhostrydeCommand.class)

View file

@ -55,7 +55,7 @@ abstract class UpdateOrDeleteAllocationTokensCommand extends ConfirmingCommand
if (tokens != null) { if (tokens != null) {
ImmutableSet<VKey<AllocationToken>> keys = ImmutableSet<VKey<AllocationToken>> keys =
tokens.stream() tokens.stream()
.map(token -> VKey.createSql(AllocationToken.class, token)) .map(token -> VKey.create(AllocationToken.class, token))
.collect(toImmutableSet()); .collect(toImmutableSet());
ImmutableSet<VKey<AllocationToken>> nonexistentKeys = ImmutableSet<VKey<AllocationToken>> nonexistentKeys =
tm().transact( tm().transact(

View file

@ -56,7 +56,7 @@ public class CreateCancellationsForOneTimesCommand extends ConfirmingCommand
tm().transact( tm().transact(
() -> { () -> {
for (Long billingEventId : ImmutableSet.copyOf(mainParameters)) { for (Long billingEventId : ImmutableSet.copyOf(mainParameters)) {
VKey<OneTime> key = VKey.createSql(OneTime.class, billingEventId); VKey<OneTime> key = VKey.create(OneTime.class, billingEventId);
if (tm().exists(key)) { if (tm().exists(key)) {
OneTime oneTime = tm().loadByKey(key); OneTime oneTime = tm().loadByKey(key);
if (alreadyCancelled(oneTime)) { if (alreadyCancelled(oneTime)) {

View file

@ -138,7 +138,7 @@ public class CreateSyntheticDomainHistoriesCommand extends ConfirmingCommand
.transact( .transact(
() -> { () -> {
Domain domain = Domain domain =
jpaTm().loadByKey(VKey.createSql(Domain.class, domainRepoId)); jpaTm().loadByKey(VKey.create(Domain.class, domainRepoId));
jpaTm() jpaTm()
.put( .put(
HistoryEntry.createBuilderForResource(domain) HistoryEntry.createBuilderForResource(domain)

View file

@ -112,7 +112,7 @@ public class RegistryJpaReadTest {
Read<Object[], String> read = Read<Object[], String> read =
RegistryJpaIO.read( RegistryJpaIO.read(
"select d, r.emailAddress from Domain d join Registrar r on" "select d, r.emailAddress from Domain d join Registrar r on"
+ " d.currentSponsorClientId = r.registrarId where r.type = :type" + " d.currentSponsorRegistrarId = r.registrarId where r.type = :type"
+ " and d.deletionTime > now()", + " and d.deletionTime > now()",
ImmutableMap.of("type", Registrar.Type.REAL), ImmutableMap.of("type", Registrar.Type.REAL),
false, false,
@ -156,7 +156,7 @@ public class RegistryJpaReadTest {
Read<Domain, String> read = Read<Domain, String> read =
RegistryJpaIO.read( RegistryJpaIO.read(
"select d from Domain d join Registrar r on" "select d from Domain d join Registrar r on"
+ " d.currentSponsorClientId = r.registrarId where r.type = :type" + " d.currentSponsorRegistrarId = r.registrarId where r.type = :type"
+ " and d.deletionTime > now()", + " and d.deletionTime > now()",
ImmutableMap.of("type", Registrar.Type.REAL), ImmutableMap.of("type", Registrar.Type.REAL),
Domain.class, Domain.class,

View file

@ -561,7 +561,7 @@ public class RdePipelineTest {
return tm().transact( return tm().transact(
() -> () ->
tm().loadByKey( tm().loadByKey(
VKey.createSql( VKey.create(
RdeRevision.class, RdeRevision.class,
RdeRevisionId.create("soy", now.toLocalDate(), mode))) RdeRevisionId.create("soy", now.toLocalDate(), mode)))
.getRevision()); .getRevision());

View file

@ -1353,7 +1353,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
private void assertAllocationTokenWasRedeemed(String token) throws Exception { private void assertAllocationTokenWasRedeemed(String token) throws Exception {
AllocationToken reloadedToken = AllocationToken reloadedToken =
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token))); tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
assertThat(reloadedToken.isRedeemed()).isTrue(); assertThat(reloadedToken.isRedeemed()).isTrue();
assertThat(reloadedToken.getRedemptionHistoryId()) assertThat(reloadedToken.getRedemptionHistoryId())
.hasValue(getHistoryEntries(reloadResourceByForeignKey()).get(0).getHistoryEntryId()); .hasValue(getHistoryEntries(reloadResourceByForeignKey()).get(0).getHistoryEntryId());
@ -1361,7 +1361,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
private void assertAllocationTokenWasNotRedeemed(String token) { private void assertAllocationTokenWasNotRedeemed(String token) {
AllocationToken reloadedToken = AllocationToken reloadedToken =
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token))); tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
assertThat(reloadedToken.isRedeemed()).isFalse(); assertThat(reloadedToken.isRedeemed()).isFalse();
} }

View file

@ -382,7 +382,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
Domain domainAtRedemptionTime = domain.cloneProjectedAtTime(redemptionEndTime); Domain domainAtRedemptionTime = domain.cloneProjectedAtTime(redemptionEndTime);
assertAboutDomains() assertAboutDomains()
.that(domainAtRedemptionTime) .that(domainAtRedemptionTime)
.hasLastEppUpdateClientId("TheRegistrar") .hasLastEppUpdateRegistrarId("TheRegistrar")
.and() .and()
.hasLastEppUpdateTime(redemptionEndTime); .hasLastEppUpdateTime(redemptionEndTime);
} }
@ -930,7 +930,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar"); .hasLastEppUpdateRegistrarId("TheRegistrar");
assertAboutHistoryEntries() assertAboutHistoryEntries()
.that(getOnlyHistoryEntryOfType(domain, DOMAIN_DELETE)) .that(getOnlyHistoryEntryOfType(domain, DOMAIN_DELETE))
.hasType(DOMAIN_DELETE) .hasType(DOMAIN_DELETE)

View file

@ -267,7 +267,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId(renewalClientId); .hasLastEppUpdateRegistrarId(renewalClientId);
assertAboutHistoryEntries().that(historyEntryDomainRenew).hasPeriodYears(renewalYears); assertAboutHistoryEntries().that(historyEntryDomainRenew).hasPeriodYears(renewalYears);
BillingEvent.OneTime renewBillingEvent = BillingEvent.OneTime renewBillingEvent =
new BillingEvent.OneTime.Builder() new BillingEvent.OneTime.Builder()
@ -332,7 +332,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
@Test @Test
private void assertAllocationTokenWasNotRedeemed(String token) { private void assertAllocationTokenWasNotRedeemed(String token) {
AllocationToken reloadedToken = AllocationToken reloadedToken =
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token))); tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
assertThat(reloadedToken.isRedeemed()).isFalse(); assertThat(reloadedToken.isRedeemed()).isFalse();
} }

View file

@ -186,7 +186,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar"); .hasLastEppUpdateRegistrarId("TheRegistrar");
assertThat(domain.getGracePeriods()).isEmpty(); assertThat(domain.getGracePeriods()).isEmpty();
assertDnsTasksEnqueued("example.tld"); assertDnsTasksEnqueued("example.tld");
// The poll message for the delete should now be gone. The only poll message should be the new // The poll message for the delete should now be gone. The only poll message should be the new
@ -255,7 +255,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar"); .hasLastEppUpdateRegistrarId("TheRegistrar");
assertThat(domain.getGracePeriods()).isEmpty(); assertThat(domain.getGracePeriods()).isEmpty();
assertDnsTasksEnqueued("example.tld"); assertDnsTasksEnqueued("example.tld");
// The poll message for the delete should now be gone. The only poll message should be the new // The poll message for the delete should now be gone. The only poll message should be the new

View file

@ -138,7 +138,7 @@ class DomainTransferApproveFlowTest
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar"); .hasLastEppUpdateRegistrarId("TheRegistrar");
// The domain TransferData should reflect the approved transfer as we expect, with // The domain TransferData should reflect the approved transfer as we expect, with
// all the speculative server-approve fields nulled out. // all the speculative server-approve fields nulled out.
assertThat(domain.getTransferData()) assertThat(domain.getTransferData())

View file

@ -138,7 +138,7 @@ class DomainTransferCancelFlowTest
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("NewRegistrar"); .hasLastEppUpdateRegistrarId("NewRegistrar");
final HistoryEntry historyEntryTransferCancel = final HistoryEntry historyEntryTransferCancel =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL); getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL);
assertAboutHistoryEntries() assertAboutHistoryEntries()

View file

@ -108,7 +108,7 @@ class DomainTransferRejectFlowTest
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar"); .hasLastEppUpdateRegistrarId("TheRegistrar");
final HistoryEntry historyEntryTransferRejected = final HistoryEntry historyEntryTransferRejected =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT); getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
assertAboutHistoryEntries() assertAboutHistoryEntries()

View file

@ -192,7 +192,7 @@ class DomainTransferRequestFlowTest
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("NewRegistrar"); .hasLastEppUpdateRegistrarId("NewRegistrar");
Trid expectedTrid = Trid expectedTrid =
Trid.create( Trid.create(
getClientTrid(), getClientTrid(),
@ -449,7 +449,7 @@ class DomainTransferRequestFlowTest
.and() .and()
.hasLastEppUpdateTime(implicitTransferTime) .hasLastEppUpdateTime(implicitTransferTime)
.and() .and()
.hasLastEppUpdateClientId("NewRegistrar"); .hasLastEppUpdateRegistrarId("NewRegistrar");
assertThat(loadByKey(domainAfterAutomaticTransfer.getAutorenewBillingEvent()).getEventTime()) assertThat(loadByKey(domainAfterAutomaticTransfer.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(expectedExpirationTime); .isEqualTo(expectedExpirationTime);
// And after the expected grace time, the grace period should be gone. // And after the expected grace time, the grace period should be gone.

View file

@ -56,7 +56,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
import com.googlecode.objectify.Key;
import google.registry.config.RegistryConfig; import google.registry.config.RegistryConfig;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.UnimplementedExtensionException; import google.registry.flows.EppException.UnimplementedExtensionException;
@ -90,6 +89,7 @@ import google.registry.flows.domain.DomainFlowUtils.UrgentAttributeNotSupportedE
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException; import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.contact.Contact; import google.registry.model.contact.Contact;
@ -214,7 +214,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.and() .and()
.hasLastEppUpdateTime(clock.nowUtc()) .hasLastEppUpdateTime(clock.nowUtc())
.and() .and()
.hasLastEppUpdateClientId("TheRegistrar") .hasLastEppUpdateRegistrarId("TheRegistrar")
.and() .and()
.hasNoAutorenewEndTime(); .hasNoAutorenewEndTime();
assertNoBillingEvents(); assertNoBillingEvents();
@ -1656,7 +1656,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
runFlow(); runFlow();
assertThat(reloadResourceByForeignKey().getNameservers()) assertThat(reloadResourceByForeignKey().getNameservers())
.doesNotContain( .doesNotContain(
Key.create(loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc()).get())); loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc())
.map(ImmutableObject::createVKey)
.get());
} }
@Test @Test

View file

@ -1,82 +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;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.StreamSubject.streams;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.model.EntityClasses.ALL_CLASSES;
import static google.registry.util.TypeUtils.hasAnnotation;
import com.google.common.collect.Ordering;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.EntitySubclass;
import java.util.Set;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link EntityClasses}. */
class EntityClassesTest {
// This implements the manual ordering we've been using for the EntityClasses class lists.
private static final Ordering<Class<?>> QUALIFIED_CLASS_NAME_ORDERING =
Ordering.natural()
.onResultOf(
clazz -> clazz.getCanonicalName().substring(clazz.getPackage().getName().length()));
@Test
void testEntityClasses_inAlphabeticalOrder() {
assertThat(ALL_CLASSES).isInStrictOrder(QUALIFIED_CLASS_NAME_ORDERING);
}
@Test
void testEntityClasses_baseEntitiesHaveUniqueKinds() {
assertWithMessage("base entity kinds")
.about(streams())
.that(ALL_CLASSES.stream().filter(hasAnnotation(Entity.class)).map(Key::getKind))
.containsNoDuplicates();
}
@Test
void testEntityClasses_entitySubclassesHaveKindsMatchingBaseEntities() {
Set<String> baseEntityKinds =
ALL_CLASSES
.stream()
.filter(hasAnnotation(Entity.class))
.map(Key::getKind)
.collect(toImmutableSet());
Set<String> entitySubclassKinds =
ALL_CLASSES
.stream()
.filter(hasAnnotation(EntitySubclass.class))
.map(Key::getKind)
.collect(toImmutableSet());
assertWithMessage("base entity kinds")
.that(baseEntityKinds)
.containsAtLeastElementsIn(entitySubclassKinds);
}
@Test
void testEntityClasses_eitherBaseEntityOrEntitySubclass() {
for (Class<?> clazz : ALL_CLASSES) {
boolean isEntityXorEntitySubclass =
clazz.isAnnotationPresent(Entity.class) ^ clazz.isAnnotationPresent(EntitySubclass.class);
assertWithMessage("class " + clazz.getSimpleName() + " is @Entity or @EntitySubclass")
.that(isEntityXorEntitySubclass)
.isTrue();
}
}
}

View file

@ -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;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.GoldenFileTestHelper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/**
* Unit tests for {@link SchemaVersion}.
*
* <p>If the test breaks, the instructions below will be printed.
*/
@DeleteAfterMigration
public class SchemaVersionTest {
@RegisterExtension
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
@Test
void testGoldenSchemaFile() {
GoldenFileTestHelper.assertThat(SchemaVersion.getSchema())
.describedAs("Datastore schema")
.createdByNomulusCommand("get_schema")
.isEqualToGolden(SchemaVersionTest.class, "schema.txt");
}
}

View file

@ -51,7 +51,7 @@ public class UpdateAutoTimestampTest {
private static UpdateAutoTimestampTestObject reload() { private static UpdateAutoTimestampTestObject reload() {
return tm().transact( return tm().transact(
() -> tm().loadByKey(VKey.createSql(UpdateAutoTimestampTestObject.class, 1L))); () -> tm().loadByKey(VKey.create(UpdateAutoTimestampTestObject.class, 1L)));
} }
@Test @Test

View file

@ -1,88 +0,0 @@
// Copyright 2021 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.common;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import google.registry.model.contact.Contact;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.host.Host;
import google.registry.testing.TestObject;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link ClassPathManager}. */
public class ClassPathManagerTest {
@Test
void getClass_classInClassRegistry_returnsClass() throws ClassNotFoundException {
/*
* Class names are used in stringified vkeys, which can be present in task queues. Class name is
* required to create a vkey. Changing these names could break task queue entries that are
* present during a rollout. If you want to change the names of any of the classses supported in
* CLASS_REGISTRY, you'll need to introduce some mechanism to deal with this. One way is to find
* the corresponding class name by calling ClassPathManager.getClassName(clazz). The classes
* below are all classes supported in CLASS_REGISTRY. This test breaks if someone changes a
* classname without preserving the original name.
*/
assertThat(ClassPathManager.getClass("Host")).isEqualTo(Host.class);
assertThat(ClassPathManager.getClass("Contact")).isEqualTo(Contact.class);
assertThat(ClassPathManager.getClass("GaeUserIdConverter")).isEqualTo(GaeUserIdConverter.class);
assertThat(ClassPathManager.getClass("Domain")).isEqualTo(Domain.class);
}
@Test
void getClass_classNotInClassRegistry_throwsException() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class, () -> ClassPathManager.getClass("DomainHistory"));
assertThat(thrown).hasMessageThat().contains("Class DomainHistory not found in class registry");
}
@Test
void getClassName_classNotInClassRegistry_throwsException() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> ClassPathManager.getClassName(DomainHistory.class));
assertThat(thrown)
.hasMessageThat()
.contains("Class DomainHistory not found in class name registry");
}
@Test
void getClassName() {
/*
* Class names are used in stringified vkeys, which can be present in task queues. Class name is
* required to create a vkey. Changing these names could break task queue entries that are
* present during a rollout. If you want to change the names of any of the classses supported in
* CLASS_NAME_REGISTRY, you'll need to introduce some mechanism to deal with this.
* ClassPathManager.getClassName(clazz) allows you to verify the corresponding name of a class.
* The classes below are all classes supported in CLASS_NAME_REGISTRY. This test breaks if
* someone changes a classname without preserving the original name.
*/
assertThat(ClassPathManager.getClassName(Host.class)).isEqualTo("Host");
assertThat(ClassPathManager.getClassName(Contact.class)).isEqualTo("Contact");
assertThat(ClassPathManager.getClassName(GaeUserIdConverter.class))
.isEqualTo("GaeUserIdConverter");
assertThat(ClassPathManager.getClassName(Domain.class)).isEqualTo("Domain");
}
@Test
void addTestEntityClass_success() {
ClassPathManager.addTestEntityClass(TestObject.class);
assertThat(ClassPathManager.getClass("TestObject")).isEqualTo(TestObject.class);
}
}

View file

@ -401,7 +401,7 @@ public class DomainSqlTest {
} }
private <T> VKey<T> createKey(Class<T> clazz, String key) { private <T> VKey<T> createKey(Class<T> clazz, String key) {
return VKey.createSql(clazz, key); return VKey.create(clazz, key);
} }
private void assertEqualDomainExcept(Domain thatDomain, String... excepts) { private void assertEqualDomainExcept(Domain thatDomain, String... excepts) {

View file

@ -166,8 +166,8 @@ public class DomainTest {
.build(); .build();
insertInDb(historyEntry, oneTimeBill, recurringBill); insertInDb(historyEntry, oneTimeBill, recurringBill);
recurringBillKey = recurringBill.createVKey(); recurringBillKey = recurringBill.createVKey();
VKey<PollMessage.Autorenew> autorenewPollKey = VKey.createSql(PollMessage.Autorenew.class, 3L); VKey<PollMessage.Autorenew> autorenewPollKey = VKey.create(PollMessage.Autorenew.class, 3L);
VKey<PollMessage.OneTime> onetimePollKey = VKey.createSql(PollMessage.OneTime.class, 1L); VKey<PollMessage.OneTime> onetimePollKey = VKey.create(PollMessage.OneTime.class, 1L);
// Set up a new persisted domain entity. // Set up a new persisted domain entity.
domain = domain =
persistResource( persistResource(
@ -524,7 +524,7 @@ public class DomainTest {
assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");
// If autorenew happens before transfer succeeds(before transfer grace period starts as well), // If autorenew happens before transfer succeeds(before transfer grace period starts as well),
// lastEppUpdateClientId should still be the current sponsor client id // lastEppUpdateRegistrarId should still be the current sponsor client id
Domain afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1)); Domain afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1));
assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime); assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime);
assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar"); assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar");

View file

@ -16,7 +16,6 @@ package google.registry.model.ofy;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.initOfy; import static google.registry.model.ofy.ObjectifyService.initOfy;
import static google.registry.testing.DatabaseHelper.newContact;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig; import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
@ -27,7 +26,7 @@ import com.googlecode.objectify.ObjectifyFilter;
import com.googlecode.objectify.ObjectifyService; import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Id;
import google.registry.model.contact.Contact; import google.registry.model.common.GaeUserIdConverter;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -81,8 +80,9 @@ class OfyFilterTest {
@Test @Test
void testKeyCreateAfterFilter() { void testKeyCreateAfterFilter() {
new OfyFilter().init(null); new OfyFilter().init(null);
Contact contact = newContact("contact1234"); GaeUserIdConverter userIdConverter = new GaeUserIdConverter();
Key.create(contact); userIdConverter.id = 1;
Key.create(userIdConverter);
} }
@Entity @Entity

View file

@ -140,6 +140,6 @@ public class PollMessageExternalKeyConverterTest {
one.getKind().isAssignableFrom(two.getKind()) one.getKind().isAssignableFrom(two.getKind())
|| two.getKind().isAssignableFrom(one.getKind())) || two.getKind().isAssignableFrom(one.getKind()))
.isTrue(); .isTrue();
assertThat(one.getSqlKey()).isEqualTo(two.getSqlKey()); assertThat(one.getKey()).isEqualTo(two.getKey());
} }
} }

View file

@ -91,13 +91,12 @@ public class PollMessageTest extends EntityTestCase {
@Test @Test
void testCloudSqlSupportForPolymorphicVKey() { void testCloudSqlSupportForPolymorphicVKey() {
insertInDb(oneTime); insertInDb(oneTime);
PollMessage persistedOneTime = loadByKey(VKey.createSql(PollMessage.class, oneTime.getId())); PollMessage persistedOneTime = loadByKey(VKey.create(PollMessage.class, oneTime.getId()));
assertThat(persistedOneTime).isInstanceOf(PollMessage.OneTime.class); assertThat(persistedOneTime).isInstanceOf(PollMessage.OneTime.class);
assertThat(persistedOneTime).isEqualTo(oneTime); assertThat(persistedOneTime).isEqualTo(oneTime);
insertInDb(autoRenew); insertInDb(autoRenew);
PollMessage persistedAutoRenew = PollMessage persistedAutoRenew = loadByKey(VKey.create(PollMessage.class, autoRenew.getId()));
loadByKey(VKey.createSql(PollMessage.class, autoRenew.getId()));
assertThat(persistedAutoRenew).isInstanceOf(PollMessage.Autorenew.class); assertThat(persistedAutoRenew).isInstanceOf(PollMessage.Autorenew.class);
assertThat(persistedAutoRenew).isEqualTo(autoRenew); assertThat(persistedAutoRenew).isEqualTo(autoRenew);
} }

View file

@ -54,8 +54,8 @@ public final class Spec11ThreatMatchTest extends EntityTestCase {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
VKey<Host> hostVKey = VKey.createSql(Host.class, "host"); VKey<Host> hostVKey = VKey.create(Host.class, "host");
VKey<Contact> registrantContactVKey = VKey.createSql(Contact.class, "contact_id"); VKey<Contact> registrantContactVKey = VKey.create(Contact.class, "contact_id");
String domainRepoId = "4-TLD"; String domainRepoId = "4-TLD";
createTld("tld"); createTld("tld");

View file

@ -51,8 +51,8 @@ public class TransferDataTest {
transferBillingEventKey = OneTime.createVKey(12345L); transferBillingEventKey = OneTime.createVKey(12345L);
otherServerApproveBillingEventKey = Cancellation.createVKey(2468L); otherServerApproveBillingEventKey = Cancellation.createVKey(2468L);
recurringBillingEventKey = Recurring.createVKey(13579L); recurringBillingEventKey = Recurring.createVKey(13579L);
autorenewPollMessageKey = VKey.createSql(PollMessage.Autorenew.class, 67890L); autorenewPollMessageKey = VKey.create(PollMessage.Autorenew.class, 67890L);
otherServerApprovePollMessageKey = VKey.createSql(PollMessage.OneTime.class, 314159L); otherServerApprovePollMessageKey = VKey.create(PollMessage.OneTime.class, 314159L);
} }
@Test @Test

View file

@ -51,9 +51,9 @@ public class StatusValueAdapterTest {
new EppResponse.Builder() new EppResponse.Builder()
.setResData( .setResData(
HostInfoData.newBuilder() HostInfoData.newBuilder()
.setCreationClientId("") .setCreationRegistrarId("")
.setCreationTime(START_OF_TIME) .setCreationTime(START_OF_TIME)
.setCurrentSponsorClientId("") .setCurrentSponsorRegistrarId("")
.setHostName("") .setHostName("")
.setInetAddresses(ImmutableSet.of()) .setInetAddresses(ImmutableSet.of())
.setRepoId("") .setRepoId("")

View file

@ -1,63 +0,0 @@
// 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.model.translators;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.newDomain;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import com.googlecode.objectify.Key;
import google.registry.model.common.ClassPathManager;
import google.registry.model.domain.Domain;
import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.TestObject;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link VKeyTranslatorFactory}. */
public class VKeyTranslatorFactoryTest {
@RegisterExtension
public final AppEngineExtension appEngine =
AppEngineExtension.builder().withCloudSql().withOfyTestEntities(TestObject.class).build();
VKeyTranslatorFactoryTest() {}
@BeforeAll
static void beforeAll() {
ClassPathManager.addTestEntityClass(TestObject.class);
}
@Test
void testEntityWithFlatKey() {
// Creating an objectify key instead of a datastore key as this should get a correctly formatted
// key path.
Domain domain = newDomain("example.com", "ROID-1", persistActiveContact("contact-1"));
Key<Domain> key = Key.create(domain);
VKey<Domain> vkey = VKeyTranslatorFactory.createVKey(key);
assertThat(vkey.getKind()).isEqualTo(Domain.class);
assertThat(vkey.getOfyKey()).isEqualTo(key);
assertThat(vkey.getSqlKey()).isEqualTo("ROID-1");
}
@Test
void testExtraEntityClass() {
TestObject testObject = TestObject.create("id", "field");
Key<TestObject> key = Key.create(testObject);
assertThat(VKeyTranslatorFactory.createVKey(key).getSqlKey()).isEqualTo("id");
}
}

View file

@ -68,14 +68,14 @@ class EntityCallbacksListenerTest {
checkAll(updated, 0, 1, 0, 1); checkAll(updated, 0, 1, 0, 1);
TestEntity testLoad = TestEntity testLoad =
jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TestEntity.class, "id"))); jpaTm().transact(() -> jpaTm().loadByKey(VKey.create(TestEntity.class, "id")));
checkAll(testLoad, 0, 0, 0, 1); checkAll(testLoad, 0, 0, 0, 1);
TestEntity testRemove = TestEntity testRemove =
jpaTm() jpaTm()
.transact( .transact(
() -> { () -> {
TestEntity removed = jpaTm().loadByKey(VKey.createSql(TestEntity.class, "id")); TestEntity removed = jpaTm().loadByKey(VKey.create(TestEntity.class, "id"));
return jpaTm().delete(removed); return jpaTm().delete(removed);
}); });
checkAll(testRemove, 0, 0, 1, 1); checkAll(testRemove, 0, 0, 1, 1);
@ -105,10 +105,10 @@ class EntityCallbacksListenerTest {
insertInDb(new TestEntity()); insertInDb(new TestEntity());
TestEntity testLoad = TestEntity testLoad =
jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TestEntity.class, "id"))); jpaTm().transact(() -> jpaTm().loadByKey(VKey.create(TestEntity.class, "id")));
assertThat(testLoad.entityPreUpdate).isEqualTo(0); assertThat(testLoad.entityPreUpdate).isEqualTo(0);
testLoad = jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TestEntity.class, "id"))); testLoad = jpaTm().transact(() -> jpaTm().loadByKey(VKey.create(TestEntity.class, "id")));
// Verify that post-load happened but pre-update didn't. // Verify that post-load happened but pre-update didn't.
assertThat(testLoad.entityPostLoad).isEqualTo(1); assertThat(testLoad.entityPostLoad).isEqualTo(1);

View file

@ -14,21 +14,12 @@
package google.registry.persistence; package google.registry.persistence;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.testing.DatabaseHelper.newDomain;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.common.ClassPathManager;
import google.registry.model.domain.Domain; import google.registry.model.domain.Domain;
import google.registry.model.host.Host; import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.RegistrarPoc; import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.testing.AppEngineExtension; import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.TestObject;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@ -36,303 +27,80 @@ import org.junit.jupiter.api.extension.RegisterExtension;
class VKeyTest { class VKeyTest {
@RegisterExtension @RegisterExtension
final AppEngineExtension appEngineExtension = final JpaIntegrationTestExtension jpa =
AppEngineExtension.builder().withCloudSql().withOfyTestEntities(TestObject.class).build(); new JpaTestExtensions.Builder().buildIntegrationTestExtension();
@BeforeAll @Test
static void beforeAll() { void testSuccess_createWithLongKey() {
ClassPathManager.addTestEntityClass(TestObject.class); VKey<PollMessage> key = VKey.create(PollMessage.class, 5L);
assertThat(key.getKey()).isEqualTo(5L);
assertThat(key.getKind()).isEqualTo(PollMessage.class);
} }
@Test @Test
void testOptionalAccessors() { void testSuccess_createWithStringKey() {
VKey<TestObject> key = VKey<Domain> key = VKey.create(Domain.class, "blah");
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo"))); assertThat(key.getKey()).isEqualTo("blah");
assertThat(key.maybeGetSqlKey().isPresent()).isTrue(); assertThat(key.getKind()).isEqualTo(Domain.class);
assertThat(key.maybeGetOfyKey().isPresent()).isTrue();
assertThat(VKey.createSql(TestObject.class, "foo").maybeGetSqlKey()).hasValue("foo");
} }
@Test @Test
void testCreateById_failsWhenParentIsNullButShouldntBe() { void testFailure_missingArguments() {
IllegalArgumentException thrown = assertThat(assertThrows(IllegalArgumentException.class, () -> VKey.create(null, "blah")))
assertThrows(IllegalArgumentException.class, () -> VKey.create(OneTime.class, 134L)); .hasMessageThat()
assertThat(thrown).hasMessageThat().contains("UpdateAutoTimestampEntity"); .isEqualTo("kind must not be null");
assertThat(assertThrows(IllegalArgumentException.class, () -> VKey.create(Domain.class, null)))
.hasMessageThat()
.isEqualTo("key must not be null");
} }
@Test @Test
void testCreateByName_failsWhenParentIsNullButShouldntBe() { void testSuccess_createFromString() {
IllegalArgumentException thrown = VKey<Domain> key = VKey.createEppVKeyFromString("kind:Domain@sql:rO0ABXQABGJsYWg");
assertThat(key.getKey()).isEqualTo("blah");
assertThat(key.getKind()).isEqualTo(Domain.class);
}
@Test
void testFailure_createFromString_missingKind() {
assertThat(
assertThrows( assertThrows(
IllegalArgumentException.class, IllegalArgumentException.class,
() -> VKey.create(RegistrarPoc.class, "fake@example.com")); () -> VKey.createEppVKeyFromString("sql:rO0ABXQABGJsYWg")))
assertThat(thrown).hasMessageThat().contains("UpdateAutoTimestampEntity"); .hasMessageThat()
.isEqualTo("\"kind\" missing from the string: sql:rO0ABXQABGJsYWg");
} }
@Test @Test
void testRestoreOfy() { void testFailure_createFromString_missingKey() {
assertThat(VKey.restoreOfyFrom(null, TestObject.class, 100)).isNull(); assertThat(
assertThrows(
IllegalArgumentException.class, () -> VKey.createEppVKeyFromString("kind:Domain")))
.hasMessageThat()
.isEqualTo("\"sql\" missing from the string: kind:Domain");
}
VKey<TestObject> key = VKey.createSql(TestObject.class, "foo"); @Test
VKey<TestObject> restored = key.restoreOfy(TestObject.class, "bar"); void testFailure_createFromString_wrongKind() {
assertThat(restored.getOfyKey()) assertThat(
.isEqualTo(Key.create(Key.create(TestObject.class, "bar"), TestObject.class, "foo"));
assertThat(restored.getSqlKey()).isEqualTo("foo");
assertThat(VKey.restoreOfyFrom(key).getOfyKey()).isEqualTo(Key.create(TestObject.class, "foo"));
restored = key.restoreOfy(OtherObject.class, "baz", TestObject.class, "bar");
assertThat(restored.getOfyKey())
.isEqualTo(
Key.create(
Key.create(Key.create(OtherObject.class, "baz"), TestObject.class, "bar"),
TestObject.class,
"foo"));
// Verify that we can use a key as the first argument.
restored = key.restoreOfy(Key.create(TestObject.class, "bar"));
assertThat(restored.getOfyKey())
.isEqualTo(Key.create(Key.create(TestObject.class, "bar"), TestObject.class, "foo"));
// Verify that we get an exception when a key is not the first argument.
IllegalArgumentException thrown =
assertThrows( assertThrows(
IllegalArgumentException.class, IllegalArgumentException.class,
() -> key.restoreOfy(TestObject.class, "foo", Key.create(TestObject.class, "bar"))); () -> VKey.createEppVKeyFromString("kind:Registry@sql:rO0ABXQABGJsYWg")))
assertThat(thrown)
.hasMessageThat() .hasMessageThat()
.contains("Objectify keys may only be used for the first argument"); .isEqualTo("Registry is not an EppResource");
// Verify other exception cases.
thrown =
assertThrows(
IllegalArgumentException.class,
() -> key.restoreOfy(TestObject.class, TestObject.class));
assertThat(thrown)
.hasMessageThat()
.contains("class google.registry.testing.TestObject used as a key value.");
thrown =
assertThrows(IllegalArgumentException.class, () -> key.restoreOfy(TestObject.class, 1.5));
assertThat(thrown).hasMessageThat().contains("Key value 1.5 must be a string or long.");
thrown = assertThrows(IllegalArgumentException.class, () -> key.restoreOfy(TestObject.class));
assertThat(thrown)
.hasMessageThat()
.contains("Missing value for last key of type class google.registry.testing.TestObject");
} }
@Test @Test
void testFromWebsafeKey() { void testSuccess_stringify() {
// Creating an objectify key instead of a datastore key as this should get a correctly formatted VKey<Domain> key = VKey.create(Domain.class, "blah");
// key path. We have to one of our actual model object classes for this, TestObject can not be String keyString = key.stringify();
// reconstructed by the VKeyTranslatorFactory. assertThat(keyString).isEqualTo("kind:Domain@sql:rO0ABXQABGJsYWg");
Domain domain = newDomain("example.com", "ROID-1", persistActiveContact("contact-1"));
Key<Domain> key = Key.create(domain);
VKey<Domain> vkey = VKey.fromWebsafeKey(key.getString());
assertThat(vkey.getKind()).isEqualTo(Domain.class);
assertThat(vkey.getOfyKey()).isEqualTo(key);
assertThat(vkey.getSqlKey()).isEqualTo("ROID-1");
}
/** Test stringify() with vkey created via different ways. */
@Test
void testStringify_sqlOnlyVKey() {
assertThat(VKey.createSql(TestObject.class, "foo").stringify())
.isEqualTo("kind:TestObject@sql:rO0ABXQAA2Zvbw");
} }
@Test @Test
void testStringify_ofyOnlyVKey() { void testSuccess_toString() {
assertThat(VKey.createOfy(TestObject.class, Key.create(TestObject.class, "foo")).stringify()) VKey<Domain> key = VKey.create(Domain.class, "blah");
.isEqualTo("kind:TestObject@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M"); String keyString = key.toString();
assertThat(keyString).isEqualTo("VKey<Domain>(sql:blah)");
} }
@Test
void testStringify_vkeyFromWebsafeKey() {
Domain domain = newDomain("example.com", "ROID-1", persistActiveContact("contact-1"));
Key<Domain> key = Key.create(domain);
VKey<Domain> vkey = VKey.fromWebsafeKey(key.getString());
assertThat(vkey.stringify())
.isEqualTo(
"kind:Domain" + "@sql:rO0ABXQABlJPSUQtMQ" + "@ofy:agR0ZXN0chILEgZEb21haW4iBlJPSUQtMQw");
}
@Test
void testStringify_sqlAndOfyVKey() {
assertThat(
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo"))).stringify())
.isEqualTo("kind:TestObject@sql:rO0ABXQAA2Zvbw@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M");
}
@Test
void testStringify_asymmetricVKey() {
assertThat(
VKey.create(TestObject.class, "test", Key.create(TestObject.create("foo"))).stringify())
.isEqualTo("kind:TestObject@sql:rO0ABXQABHRlc3Q@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M");
}
/** Test create() via different vkey string representations. */
@Test
void testCreate_stringifedVKey_sqlOnlyVKeyString() {
assertThat(VKey.create("kind:TestObject@sql:rO0ABXQAA2Zvbw"))
.isEqualTo(VKey.createSql(TestObject.class, "foo"));
}
@Test
void testCreate_stringifiedVKey_resourceKeyFromTaskQueue() throws Exception {
VKey<Host> vkeyFromNewWebsafeKey =
VKey.create(
"kind:Host@sql:rO0ABXQADzZCQjJGNDc2LUdPT0dMRQ@ofy:ahdzfm"
+ "RvbWFpbi1yZWdpc3RyeS1hbHBoYXIhCxIMSG9zdFJlc291cmNlIg82QkIyRjQ3Ni1HT09HTEUM");
assertThat(vkeyFromNewWebsafeKey.getSqlKey()).isEqualTo("6BB2F476-GOOGLE");
assertThat(vkeyFromNewWebsafeKey.getOfyKey().getString())
.isEqualTo(
"ahdzfmRvbWFpbi1yZWdpc3RyeS1hbHBoYXIhCxIMSG9zdFJlc291cmNlIg82QkIyRjQ3Ni1HT09HTEUM");
}
@Test
void testCreate_stringifedVKey_ofyOnlyVKeyString() {
assertThat(VKey.create("kind:TestObject@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M"))
.isEqualTo(VKey.createOfy(TestObject.class, Key.create(TestObject.class, "foo")));
}
@Test
void testCreate_stringifedVKey_asymmetricVKeyString() {
assertThat(
VKey.create(
"kind:TestObject@sql:rO0ABXQABHRlc3Q@ofy:agR0ZXN0cjELEg9Fb"
+ "nRpdHlHcm91cFJvb3QiCWNyb3NzLXRsZAwLEgpUZXN0T2JqZWN0IgNmb28M"))
.isEqualTo(VKey.create(TestObject.class, "test", Key.create(TestObject.create("foo"))));
}
@Test
void testCreate_stringifedVKey_sqlAndOfyVKeyString() {
assertThat(
VKey.create(
"kind:TestObject@sql:rO0ABXQAA2Zvbw@ofy:agR0ZXN0cjELEg9Fbn"
+ "RpdHlHcm91cFJvb3QiCWNyb3NzLXRsZAwLEgpUZXN0T2JqZWN0IgNmb28M"))
.isEqualTo(VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo"))));
}
@Test
void testCreate_stringifyVkey_fromWebsafeKey() {
assertThat(
VKey.create(
"kind:Domain@sql:rO0ABXQABlJPSUQtMQ"
+ "@ofy:agR0ZXN0chYLEgpEb21haW5CYXNlIgZST0lELTEM"))
.isEqualTo(
VKey.fromWebsafeKey(
Key.create(newDomain("example.com", "ROID-1", persistActiveContact("contact-1")))
.getString()));
}
@Test
void testCreate_stringifedVKey_websafeKey() {
assertThat(VKey.create("agR0ZXN0chkLEgZEb21haW4iDUdBU0RHSDQyMkQtSUQM"))
.isEqualTo(VKey.fromWebsafeKey("agR0ZXN0chkLEgZEb21haW4iDUdBU0RHSDQyMkQtSUQM"));
}
@Test
void testCreate_invalidStringifiedVKey_failure() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class, () -> VKey.create("kind:TestObject@sq:l@ofya:bc"));
assertThat(thrown)
.hasMessageThat()
.contains("Cannot parse key string: kind:TestObject@sq:l@ofya:bc");
}
@Test
void testCreate_invalidOfyKeyString_failure() {
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> VKey.create("invalid"));
assertThat(thrown).hasMessageThat().contains("Could not parse Reference");
}
/** Test stringify() then create() flow. */
@Test
void testStringifyThenCreate_sqlOnlyVKey_testObject_stringKey_success() {
VKey<TestObject> vkey = VKey.createSql(TestObject.class, "foo");
VKey<TestObject> newVkey = VKey.create(vkey.stringify());
assertThat(newVkey).isEqualTo(vkey);
}
@Test
void testStringifyThenCreate_sqlOnlyVKey_testObject_longKey_success() {
VKey<TestObject> vkey = VKey.createSql(TestObject.class, (long) 12345);
VKey<TestObject> newVkey = VKey.create(vkey.stringify());
assertThat(newVkey).isEqualTo(vkey);
}
@Test
void testCreate_createFromExistingOfyKey_success() {
String keyString =
Key.create(newDomain("example.com", "ROID-1", persistActiveContact("contact-1")))
.getString();
assertThat(VKey.fromWebsafeKey(keyString)).isEqualTo(VKey.create(keyString));
}
@Test
void testStringifyThenCreate_ofyOnlyVKey_testObject_success() {
VKey<TestObject> vkey =
VKey.createOfy(TestObject.class, Key.create(TestObject.class, "tmpKey"));
assertThat(VKey.create(vkey.stringify())).isEqualTo(vkey);
}
@Test
void testStringifyThenCreate_ofyOnlyVKey_testObject_websafeString_success() {
VKey<TestObject> vkey = VKey.fromWebsafeKey(Key.create(TestObject.create("foo")).getString());
assertThat(VKey.create(vkey.stringify())).isEqualTo(vkey);
}
@Test
void testStringifyThenCreate_sqlAndOfyVKey_success() {
VKey<TestObject> vkey =
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo")));
assertThat(VKey.create(vkey.stringify())).isEqualTo(vkey);
}
@Test
void testStringifyThenCreate_asymmetricVKey_success() {
VKey<TestObject> vkey =
VKey.create(TestObject.class, "sqlKey", Key.create(TestObject.create("foo")));
assertThat(VKey.create(vkey.stringify())).isEqualTo(vkey);
}
@Test
void testStringifyThenCreate_symmetricVKey_success() {
VKey<TestObject> vkey = TestObject.create("foo").key();
assertThat(VKey.create(vkey.stringify())).isEqualTo(vkey);
}
@Test
void testToString_sqlOnlyVKey() {
assertThat(VKey.createSql(TestObject.class, "testId").toString())
.isEqualTo("VKey<TestObject>(sql:testId)");
}
@Test
void testToString_ofyOnlyVKey_withName() {
assertThat(
VKey.createOfy(TestObject.class, Key.create(TestObject.class, "testName")).toString())
.isEqualTo("VKey<TestObject>(ofy:testName)");
}
@Test
void testToString_ofyOnlyVKey_withId() {
assertThat(VKey.createOfy(TestObject.class, Key.create(TestObject.class, 12345)).toString())
.isEqualTo("VKey<TestObject>(ofy:12345)");
}
@Test
void testToString_sqlAndOfyVKey() {
assertThat(
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("ofy"))).toString())
.isEqualTo("VKey<TestObject>(sql:foo,ofy:ofy)");
}
@Entity
static class OtherObject {}
} }

View file

@ -66,8 +66,7 @@ public class InetAddressSetConverterTest {
insertInDb(testEntity); insertInDb(testEntity);
InetAddressSetTestEntity persisted = InetAddressSetTestEntity persisted =
jpaTm() jpaTm()
.transact( .transact(() -> jpaTm().loadByKey(VKey.create(InetAddressSetTestEntity.class, "id")));
() -> jpaTm().loadByKey(VKey.createSql(InetAddressSetTestEntity.class, "id")));
assertThat(persisted.addresses).isEqualTo(inetAddresses); assertThat(persisted.addresses).isEqualTo(inetAddresses);
} }

View file

@ -56,8 +56,7 @@ public class LocalDateConverterTest {
LocalDateConverterTestEntity entity = new LocalDateConverterTestEntity(date); LocalDateConverterTestEntity entity = new LocalDateConverterTestEntity(date);
insertInDb(entity); insertInDb(entity);
return jpaTm() return jpaTm()
.transact( .transact(() -> jpaTm().loadByKey(VKey.create(LocalDateConverterTestEntity.class, "id")));
() -> jpaTm().loadByKey(VKey.createSql(LocalDateConverterTestEntity.class, "id")));
} }
/** Override entity name to avoid the nested class reference. */ /** Override entity name to avoid the nested class reference. */

View file

@ -46,9 +46,9 @@ public class VKeyConverterTest {
@Test @Test
void testRoundTrip() { void testRoundTrip() {
TestStringEntity stringEntity = new TestStringEntity("TheRealSpartacus"); TestStringEntity stringEntity = new TestStringEntity("TheRealSpartacus");
VKey<TestStringEntity> stringKey = VKey.createSql(TestStringEntity.class, "TheRealSpartacus"); VKey<TestStringEntity> stringKey = VKey.create(TestStringEntity.class, "TheRealSpartacus");
TestLongEntity longEntity = new TestLongEntity(300L); TestLongEntity longEntity = new TestLongEntity(300L);
VKey<TestLongEntity> longKey = VKey.createSql(TestLongEntity.class, 300L); VKey<TestLongEntity> longKey = VKey.create(TestLongEntity.class, 300L);
TestEntity original = new TestEntity(1984L, stringKey, longKey); TestEntity original = new TestEntity(1984L, stringKey, longKey);
insertInDb(stringEntity, longEntity, original); insertInDb(stringEntity, longEntity, original);

View file

@ -60,11 +60,11 @@ class JpaTransactionManagerImplTest {
private final FakeClock fakeClock = new FakeClock(); private final FakeClock fakeClock = new FakeClock();
private final TestEntity theEntity = new TestEntity("theEntity", "foo"); private final TestEntity theEntity = new TestEntity("theEntity", "foo");
private final VKey<TestEntity> theEntityKey = VKey.createSql(TestEntity.class, "theEntity"); private final VKey<TestEntity> theEntityKey = VKey.create(TestEntity.class, "theEntity");
private final TestCompoundIdEntity compoundIdEntity = private final TestCompoundIdEntity compoundIdEntity =
new TestCompoundIdEntity("compoundIdEntity", 10, "foo"); new TestCompoundIdEntity("compoundIdEntity", 10, "foo");
private final VKey<TestCompoundIdEntity> compoundIdEntityKey = private final VKey<TestCompoundIdEntity> compoundIdEntityKey =
VKey.createSql(TestCompoundIdEntity.class, new CompoundId("compoundIdEntity", 10)); VKey.create(TestCompoundIdEntity.class, new CompoundId("compoundIdEntity", 10));
private final ImmutableList<TestEntity> moreEntities = private final ImmutableList<TestEntity> moreEntities =
ImmutableList.of( ImmutableList.of(
new TestEntity("entity1", "foo"), new TestEntity("entity1", "foo"),
@ -228,8 +228,7 @@ class JpaTransactionManagerImplTest {
jpaTm().transact(() -> jpaTm().insert(entity)); jpaTm().transact(() -> jpaTm().insert(entity));
assertThat(existsInDb(entity)).isTrue(); assertThat(existsInDb(entity)).isTrue();
assertThat( assertThat(
loadByKey( loadByKey(VKey.create(TestNamedCompoundIdEntity.class, new NamedCompoundId("foo", 1))))
VKey.createSql(TestNamedCompoundIdEntity.class, new NamedCompoundId("foo", 1))))
.isEqualTo(entity); .isEqualTo(entity);
} }
@ -289,7 +288,7 @@ class JpaTransactionManagerImplTest {
void update_succeeds() { void update_succeeds() {
insertInDb(theEntity); insertInDb(theEntity);
TestEntity persisted = TestEntity persisted =
jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TestEntity.class, "theEntity"))); jpaTm().transact(() -> jpaTm().loadByKey(VKey.create(TestEntity.class, "theEntity")));
assertThat(persisted.data).isEqualTo("foo"); assertThat(persisted.data).isEqualTo("foo");
theEntity.data = "bar"; theEntity.data = "bar";
jpaTm().transact(() -> jpaTm().update(theEntity)); jpaTm().transact(() -> jpaTm().update(theEntity));
@ -415,7 +414,7 @@ class JpaTransactionManagerImplTest {
jpaTm() jpaTm()
.loadByKeysIfPresent( .loadByKeysIfPresent(
ImmutableList.of( ImmutableList.of(
theEntityKey, VKey.createSql(TestEntity.class, "does-not-exist"))); theEntityKey, VKey.create(TestEntity.class, "does-not-exist")));
assertThat(results).containsExactly(theEntityKey, theEntity); assertThat(results).containsExactly(theEntityKey, theEntity);
assertDetachedFromEntityManager(results.get(theEntityKey)); assertDetachedFromEntityManager(results.get(theEntityKey));

View file

@ -23,18 +23,17 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.truth.Truth8; import com.google.common.truth.Truth8;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension; import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -53,13 +52,11 @@ public class TransactionManagerTest {
new TestEntity("entity3", "qux")); new TestEntity("entity3", "qux"));
@RegisterExtension @RegisterExtension
public final AppEngineExtension appEngine = public final JpaUnitTestExtension jpa =
AppEngineExtension.builder() new JpaTestExtensions.Builder()
.withClock(fakeClock) .withClock(fakeClock)
.withCloudSql() .withEntityClass(TestEntity.class, TestEntityBase.class)
.withOfyTestEntities(TestEntity.class) .buildUnitTestExtension();
.withJpaUnitTestEntities(TestEntity.class, TestEntityBase.class)
.build();
TransactionManagerTest() {} TransactionManagerTest() {}
@ -116,7 +113,7 @@ public class TransactionManagerTest {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
assertEntityExists(theEntity); assertEntityExists(theEntity);
assertThat(tm().transact(() -> tm().loadByKey(theEntity.key()))).isEqualTo(theEntity); assertThat(tm().transact(() -> tm().loadByKey(theEntity.createVKey()))).isEqualTo(theEntity);
} }
@Test @Test
@ -131,17 +128,17 @@ public class TransactionManagerTest {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
tm().transact(() -> tm().put(theEntity)); tm().transact(() -> tm().put(theEntity));
assertEntityExists(theEntity); assertEntityExists(theEntity);
assertThat(tm().transact(() -> tm().loadByKey(theEntity.key()))).isEqualTo(theEntity); assertThat(tm().transact(() -> tm().loadByKey(theEntity.createVKey()))).isEqualTo(theEntity);
} }
@Test @Test
void saveNewOrUpdate_updatesExistingEntity() { void saveNewOrUpdate_updatesExistingEntity() {
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
TestEntity persisted = tm().transact(() -> tm().loadByKey(theEntity.key())); TestEntity persisted = tm().transact(() -> tm().loadByKey(theEntity.createVKey()));
assertThat(persisted.data).isEqualTo("foo"); assertThat(persisted.data).isEqualTo("foo");
theEntity.data = "bar"; theEntity.data = "bar";
tm().transact(() -> tm().put(theEntity)); tm().transact(() -> tm().put(theEntity));
persisted = tm().transact(() -> tm().loadByKey(theEntity.key())); persisted = tm().transact(() -> tm().loadByKey(theEntity.createVKey()));
assertThat(persisted.data).isEqualTo("bar"); assertThat(persisted.data).isEqualTo("bar");
} }
@ -156,14 +153,11 @@ public class TransactionManagerTest {
void update_succeeds() { void update_succeeds() {
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
TestEntity persisted = TestEntity persisted =
tm().transact( tm().transact(() -> tm().loadByKey(VKey.create(TestEntity.class, theEntity.name)));
() ->
tm().loadByKey(
VKey.create(TestEntity.class, theEntity.name, Key.create(theEntity))));
assertThat(persisted.data).isEqualTo("foo"); assertThat(persisted.data).isEqualTo("foo");
theEntity.data = "bar"; theEntity.data = "bar";
tm().transact(() -> tm().update(theEntity)); tm().transact(() -> tm().update(theEntity));
persisted = tm().transact(() -> tm().loadByKey(theEntity.key())); persisted = tm().transact(() -> tm().loadByKey(theEntity.createVKey()));
assertThat(persisted.data).isEqualTo("bar"); assertThat(persisted.data).isEqualTo("bar");
} }
@ -171,7 +165,7 @@ public class TransactionManagerTest {
void load_succeeds() { void load_succeeds() {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
TestEntity persisted = tm().transact(() -> tm().loadByKey(theEntity.key())); TestEntity persisted = tm().transact(() -> tm().loadByKey(theEntity.createVKey()));
assertThat(persisted.name).isEqualTo("theEntity"); assertThat(persisted.name).isEqualTo("theEntity");
assertThat(persisted.data).isEqualTo("foo"); assertThat(persisted.data).isEqualTo("foo");
} }
@ -180,14 +174,16 @@ public class TransactionManagerTest {
void load_throwsOnMissingElement() { void load_throwsOnMissingElement() {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
assertThrows( assertThrows(
NoSuchElementException.class, () -> tm().transact(() -> tm().loadByKey(theEntity.key()))); NoSuchElementException.class,
() -> tm().transact(() -> tm().loadByKey(theEntity.createVKey())));
} }
@Test @Test
void maybeLoad_succeeds() { void maybeLoad_succeeds() {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
TestEntity persisted = tm().transact(() -> tm().loadByKeyIfPresent(theEntity.key()).get()); TestEntity persisted =
tm().transact(() -> tm().loadByKeyIfPresent(theEntity.createVKey()).get());
assertThat(persisted.name).isEqualTo("theEntity"); assertThat(persisted.name).isEqualTo("theEntity");
assertThat(persisted.data).isEqualTo("foo"); assertThat(persisted.data).isEqualTo("foo");
} }
@ -195,21 +191,22 @@ public class TransactionManagerTest {
@Test @Test
void maybeLoad_nonExistentObject() { void maybeLoad_nonExistentObject() {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
assertThat(tm().transact(() -> tm().loadByKeyIfPresent(theEntity.key())).isPresent()).isFalse(); assertThat(tm().transact(() -> tm().loadByKeyIfPresent(theEntity.createVKey())).isPresent())
.isFalse();
} }
@Test @Test
void delete_succeeds() { void delete_succeeds() {
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
assertEntityExists(theEntity); assertEntityExists(theEntity);
tm().transact(() -> tm().delete(theEntity.key())); tm().transact(() -> tm().delete(theEntity.createVKey()));
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
} }
@Test @Test
void delete_doNothingWhenEntityNotExist() { void delete_doNothingWhenEntityNotExist() {
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
tm().transact(() -> tm().delete(theEntity.key())); tm().transact(() -> tm().delete(theEntity.createVKey()));
assertEntityNotExist(theEntity); assertEntityNotExist(theEntity);
} }
@ -218,7 +215,7 @@ public class TransactionManagerTest {
assertAllEntitiesNotExist(moreEntities); assertAllEntitiesNotExist(moreEntities);
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
Set<VKey<TestEntity>> keys = Set<VKey<TestEntity>> keys =
moreEntities.stream().map(TestEntity::key).collect(toImmutableSet()); moreEntities.stream().map(TestEntity::createVKey).collect(toImmutableSet());
assertAllEntitiesExist(moreEntities); assertAllEntitiesExist(moreEntities);
tm().transact(() -> tm().delete(keys)); tm().transact(() -> tm().delete(keys));
assertAllEntitiesNotExist(moreEntities); assertAllEntitiesNotExist(moreEntities);
@ -229,7 +226,7 @@ public class TransactionManagerTest {
assertAllEntitiesNotExist(moreEntities); assertAllEntitiesNotExist(moreEntities);
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
List<VKey<TestEntity>> keys = List<VKey<TestEntity>> keys =
moreEntities.stream().map(TestEntity::key).collect(toImmutableList()); moreEntities.stream().map(TestEntity::createVKey).collect(toImmutableList());
assertAllEntitiesExist(moreEntities); assertAllEntitiesExist(moreEntities);
tm().transact(() -> tm().delete(keys.get(0))); tm().transact(() -> tm().delete(keys.get(0)));
assertEntityNotExist(moreEntities.get(0)); assertEntityNotExist(moreEntities.get(0));
@ -250,9 +247,9 @@ public class TransactionManagerTest {
assertAllEntitiesNotExist(moreEntities); assertAllEntitiesNotExist(moreEntities);
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
List<VKey<TestEntity>> keys = List<VKey<TestEntity>> keys =
moreEntities.stream().map(TestEntity::key).collect(toImmutableList()); moreEntities.stream().map(TestEntity::createVKey).collect(toImmutableList());
assertThat(tm().transact(() -> tm().loadByKeys(keys))) assertThat(tm().transact(() -> tm().loadByKeys(keys)))
.isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::key)); .isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::createVKey));
} }
@Test @Test
@ -260,11 +257,11 @@ public class TransactionManagerTest {
assertAllEntitiesNotExist(moreEntities); assertAllEntitiesNotExist(moreEntities);
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
ImmutableList<VKey<TestEntity>> keys = ImmutableList<VKey<TestEntity>> keys =
moreEntities.stream().map(TestEntity::key).collect(toImmutableList()); moreEntities.stream().map(TestEntity::createVKey).collect(toImmutableList());
ImmutableList<VKey<TestEntity>> doubleKeys = ImmutableList<VKey<TestEntity>> doubleKeys =
Stream.concat(keys.stream(), keys.stream()).collect(toImmutableList()); Stream.concat(keys.stream(), keys.stream()).collect(toImmutableList());
assertThat(tm().transact(() -> tm().loadByKeys(doubleKeys))) assertThat(tm().transact(() -> tm().loadByKeys(doubleKeys)))
.isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::key)); .isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::createVKey));
} }
@Test @Test
@ -273,7 +270,7 @@ public class TransactionManagerTest {
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
List<VKey<TestEntity>> keys = List<VKey<TestEntity>> keys =
Stream.concat(moreEntities.stream(), Stream.of(new TestEntity("dark", "matter"))) Stream.concat(moreEntities.stream(), Stream.of(new TestEntity("dark", "matter")))
.map(TestEntity::key) .map(TestEntity::createVKey)
.collect(toImmutableList()); .collect(toImmutableList());
assertThat( assertThat(
assertThrows( assertThrows(
@ -288,10 +285,10 @@ public class TransactionManagerTest {
tm().transact(() -> tm().insertAll(moreEntities)); tm().transact(() -> tm().insertAll(moreEntities));
List<VKey<TestEntity>> keys = List<VKey<TestEntity>> keys =
Stream.concat(moreEntities.stream(), Stream.of(new TestEntity("dark", "matter"))) Stream.concat(moreEntities.stream(), Stream.of(new TestEntity("dark", "matter")))
.map(TestEntity::key) .map(TestEntity::createVKey)
.collect(toImmutableList()); .collect(toImmutableList());
assertThat(tm().transact(() -> tm().loadByKeysIfPresent(keys))) assertThat(tm().transact(() -> tm().loadByKeysIfPresent(keys)))
.isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::key)); .isEqualTo(Maps.uniqueIndex(moreEntities, TestEntity::createVKey));
} }
@Test @Test
@ -322,8 +319,8 @@ public class TransactionManagerTest {
tm().transact( tm().transact(
() -> () ->
tm().loadByEntitiesIfPresent(moreEntities).stream() tm().loadByEntitiesIfPresent(moreEntities).stream()
.map(TestEntity::key) .map(TestEntity::createVKey)
.map(VKey::getSqlKey) .map(VKey::getKey)
.collect(toImmutableList()))) .collect(toImmutableList())))
.containsExactly("entity2", "entity3"); .containsExactly("entity2", "entity3");
} }
@ -355,10 +352,10 @@ public class TransactionManagerTest {
tm().transact(() -> tm().insert(theEntity)); tm().transact(() -> tm().insert(theEntity));
tm().transact( tm().transact(
() -> { () -> {
TestEntity e = tm().loadByKey(theEntity.key()); TestEntity e = tm().loadByKey(theEntity.createVKey());
e.data = "some other data!"; e.data = "some other data!";
}); });
assertThat(tm().transact(() -> tm().loadByKey(theEntity.key())).data).isEqualTo("foo"); assertThat(tm().transact(() -> tm().loadByKey(theEntity.createVKey())).data).isEqualTo("foo");
} }
private static void assertEntityExists(TestEntity entity) { private static void assertEntityExists(TestEntity entity) {
@ -383,7 +380,7 @@ public class TransactionManagerTest {
@MappedSuperclass @MappedSuperclass
@Embeddable @Embeddable
private static class TestEntityBase extends ImmutableObject { private static class TestEntityBase extends ImmutableObject {
@Id @javax.persistence.Id protected String name; @Id protected String name;
TestEntityBase(String name) { TestEntityBase(String name) {
this.name = name; this.name = name;
@ -392,8 +389,7 @@ public class TransactionManagerTest {
TestEntityBase() {} TestEntityBase() {}
} }
@Entity(name = "TxnMgrTestEntity") @Entity(name = "TestEntity")
@javax.persistence.Entity(name = "TestEntity")
private static class TestEntity extends TestEntityBase { private static class TestEntity extends TestEntityBase {
private String data; private String data;
@ -405,8 +401,9 @@ public class TransactionManagerTest {
this.data = data; this.data = data;
} }
public VKey<TestEntity> key() { @Override
return VKey.create(TestEntity.class, name, Key.create(this)); public VKey<TestEntity> createVKey() {
return VKey.create(TestEntity.class, name);
} }
} }
} }

View file

@ -49,7 +49,7 @@ public class RegistrarDaoTest {
JpaIntegrationWithCoverageExtension jpa = JpaIntegrationWithCoverageExtension jpa =
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension(); new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
private final VKey<Registrar> registrarKey = VKey.createSql(Registrar.class, "registrarId"); private final VKey<Registrar> registrarKey = VKey.create(Registrar.class, "registrarId");
private Registrar testRegistrar; private Registrar testRegistrar;

View file

@ -161,7 +161,7 @@ abstract class AbstractEppResourceSubject<
return andChainer(); return andChainer();
} }
public And<S> hasLastEppUpdateClientId(String registrarId) { public And<S> hasLastEppUpdateRegistrarId(String registrarId) {
return hasValue( return hasValue(
registrarId, actual.getLastEppUpdateRegistrarId(), "getLastEppUpdateRegistrarId()"); registrarId, actual.getLastEppUpdateRegistrarId(), "getLastEppUpdateRegistrarId()");
} }

Some files were not shown because too many files have changed in this diff Show more