mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 03:57:51 +02:00
Add BillingVKey to restore symmetric VKey in GracePeriodBase (#902)
* Use PollMessageVKey to replace VKey<PollMessage> in DomainBase * Revert changes to DomainContent * Use BillingVKey in GracePeriodBase to restore symmetric vkey * Rebase on HEAD
This commit is contained in:
parent
3809338b6c
commit
c6f89e9474
32 changed files with 3164 additions and 2677 deletions
|
@ -110,7 +110,6 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.tmch.LordnTaskUtils;
|
import google.registry.tmch.LordnTaskUtils;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -372,7 +371,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
|
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
|
||||||
entitiesToSave.add(
|
entitiesToSave.add(
|
||||||
allocationTokenFlowUtils.redeemToken(
|
allocationTokenFlowUtils.redeemToken(
|
||||||
allocationToken.get(), DomainHistoryVKey.create(Key.create(historyEntry))));
|
allocationToken.get(), HistoryEntry.createVKey(Key.create(historyEntry))));
|
||||||
}
|
}
|
||||||
enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice);
|
enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -107,7 +108,7 @@ public class AllocationTokenFlowUtils {
|
||||||
|
|
||||||
/** Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy. */
|
/** Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy. */
|
||||||
public AllocationToken redeemToken(
|
public AllocationToken redeemToken(
|
||||||
AllocationToken token, DomainHistoryVKey redemptionHistoryEntry) {
|
AllocationToken token, VKey<? extends HistoryEntry> redemptionHistoryEntry) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
TokenType.SINGLE_USE.equals(token.getTokenType()),
|
TokenType.SINGLE_USE.equals(token.getTokenType()),
|
||||||
"Only SINGLE_USE tokens can be marked as redeemed");
|
"Only SINGLE_USE tokens can be marked as redeemed");
|
||||||
|
|
|
@ -23,6 +23,8 @@ import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Recurring;
|
import google.registry.model.billing.BillingEvent.Recurring;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.ofy.ObjectifyService;
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -82,10 +84,8 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
|
||||||
instance.domainRepoId = checkArgumentNotNull(domainRepoId);
|
instance.domainRepoId = checkArgumentNotNull(domainRepoId);
|
||||||
instance.expirationTime = checkArgumentNotNull(expirationTime);
|
instance.expirationTime = checkArgumentNotNull(expirationTime);
|
||||||
instance.clientId = checkArgumentNotNull(clientId);
|
instance.clientId = checkArgumentNotNull(clientId);
|
||||||
instance.billingEventOneTime = billingEventOneTime;
|
instance.billingEventOneTime = BillingEventVKey.create(billingEventOneTime);
|
||||||
instance.billingEventOneTimeHistoryId = DomainBase.getHistoryId(billingEventOneTime);
|
instance.billingEventRecurring = BillingRecurrenceVKey.create(billingEventRecurring);
|
||||||
instance.billingEventRecurring = billingEventRecurring;
|
|
||||||
instance.billingEventRecurringHistoryId = DomainBase.getHistoryId(billingEventRecurring);
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,6 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
|
||||||
public GracePeriod cloneAfterOfyLoad(String domainRepoId) {
|
public GracePeriod cloneAfterOfyLoad(String domainRepoId) {
|
||||||
GracePeriod clone = clone(this);
|
GracePeriod clone = clone(this);
|
||||||
clone.domainRepoId = checkArgumentNotNull(domainRepoId);
|
clone.domainRepoId = checkArgumentNotNull(domainRepoId);
|
||||||
clone.restoreHistoryIds();
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +189,7 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
|
||||||
*/
|
*/
|
||||||
public GracePeriod cloneWithRecurringBillingEvent(VKey<BillingEvent.Recurring> recurring) {
|
public GracePeriod cloneWithRecurringBillingEvent(VKey<BillingEvent.Recurring> recurring) {
|
||||||
GracePeriod clone = clone(this);
|
GracePeriod clone = clone(this);
|
||||||
clone.billingEventRecurring = recurring;
|
clone.billingEventRecurring = BillingRecurrenceVKey.create(recurring);
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,9 +231,7 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
|
||||||
instance.expirationTime = gracePeriod.expirationTime;
|
instance.expirationTime = gracePeriod.expirationTime;
|
||||||
instance.clientId = gracePeriod.clientId;
|
instance.clientId = gracePeriod.clientId;
|
||||||
instance.billingEventOneTime = gracePeriod.billingEventOneTime;
|
instance.billingEventOneTime = gracePeriod.billingEventOneTime;
|
||||||
instance.billingEventOneTimeHistoryId = gracePeriod.billingEventOneTimeHistoryId;
|
|
||||||
instance.billingEventRecurring = gracePeriod.billingEventRecurring;
|
instance.billingEventRecurring = gracePeriod.billingEventRecurring;
|
||||||
instance.billingEventRecurringHistoryId = gracePeriod.billingEventRecurringHistoryId;
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
|
|
||||||
package google.registry.model.domain;
|
package google.registry.model.domain;
|
||||||
|
|
||||||
import com.googlecode.objectify.Key;
|
|
||||||
import com.googlecode.objectify.annotation.Embed;
|
import com.googlecode.objectify.annotation.Embed;
|
||||||
import com.googlecode.objectify.annotation.Ignore;
|
import com.googlecode.objectify.annotation.Ignore;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.ModelUtils;
|
import google.registry.model.ModelUtils;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.OneTime;
|
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -68,24 +68,16 @@ public class GracePeriodBase extends ImmutableObject {
|
||||||
* billingEventRecurring}) or for redemption grace periods (since deletes have no cost).
|
* billingEventRecurring}) or for redemption grace periods (since deletes have no cost).
|
||||||
*/
|
*/
|
||||||
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
||||||
@Column(name = "billing_event_id")
|
@Access(AccessType.FIELD)
|
||||||
VKey<OneTime> billingEventOneTime = null;
|
BillingEventVKey billingEventOneTime = null;
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Column(name = "billing_event_history_id")
|
|
||||||
Long billingEventOneTimeHistoryId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recurring billing event corresponding to the action that triggered this grace period, if
|
* The recurring billing event corresponding to the action that triggered this grace period, if
|
||||||
* applicable - i.e. if the action was an autorenew - or null in all other cases.
|
* applicable - i.e. if the action was an autorenew - or null in all other cases.
|
||||||
*/
|
*/
|
||||||
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
// NB: Would @IgnoreSave(IfNull.class), but not allowed for @Embed collections.
|
||||||
@Column(name = "billing_recurrence_id")
|
@Access(AccessType.FIELD)
|
||||||
VKey<BillingEvent.Recurring> billingEventRecurring = null;
|
BillingRecurrenceVKey billingEventRecurring = null;
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Column(name = "billing_recurrence_history_id")
|
|
||||||
Long billingEventRecurringHistoryId;
|
|
||||||
|
|
||||||
public long getGracePeriodId() {
|
public long getGracePeriodId() {
|
||||||
return gracePeriodId;
|
return gracePeriodId;
|
||||||
|
@ -123,8 +115,7 @@ public class GracePeriodBase extends ImmutableObject {
|
||||||
* period is not AUTO_RENEW.
|
* period is not AUTO_RENEW.
|
||||||
*/
|
*/
|
||||||
public VKey<BillingEvent.OneTime> getOneTimeBillingEvent() {
|
public VKey<BillingEvent.OneTime> getOneTimeBillingEvent() {
|
||||||
restoreOfyKeys();
|
return billingEventOneTime == null ? null : billingEventOneTime.createVKey();
|
||||||
return billingEventOneTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,18 +123,7 @@ public class GracePeriodBase extends ImmutableObject {
|
||||||
* period is AUTO_RENEW.
|
* period is AUTO_RENEW.
|
||||||
*/
|
*/
|
||||||
public VKey<BillingEvent.Recurring> getRecurringBillingEvent() {
|
public VKey<BillingEvent.Recurring> getRecurringBillingEvent() {
|
||||||
restoreOfyKeys();
|
return billingEventRecurring == null ? null : billingEventRecurring.createVKey();
|
||||||
return billingEventRecurring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores history ids for composite VKeys after a load from datastore.
|
|
||||||
*
|
|
||||||
* <p>For use by DomainContent.load() ONLY.
|
|
||||||
*/
|
|
||||||
protected void restoreHistoryIds() {
|
|
||||||
billingEventOneTimeHistoryId = DomainBase.getHistoryId(billingEventOneTime);
|
|
||||||
billingEventRecurringHistoryId = DomainBase.getHistoryId(billingEventRecurring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,7 +132,6 @@ public class GracePeriodBase extends ImmutableObject {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Map<Field, Object> getSignificantFields() {
|
protected Map<Field, Object> getSignificantFields() {
|
||||||
restoreOfyKeys();
|
|
||||||
// Can't use streams or ImmutableMap because we can have null values.
|
// Can't use streams or ImmutableMap because we can have null values.
|
||||||
Map<Field, Object> result = new LinkedHashMap();
|
Map<Field, Object> result = new LinkedHashMap();
|
||||||
for (Map.Entry<Field, Object> entry : ModelUtils.getFieldValues(this).entrySet()) {
|
for (Map.Entry<Field, Object> entry : ModelUtils.getFieldValues(this).entrySet()) {
|
||||||
|
@ -162,33 +141,4 @@ public class GracePeriodBase extends ImmutableObject {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Restores Ofy keys in the billing events.
|
|
||||||
*
|
|
||||||
* <p>This must be called by all methods that access the one time or recurring billing event keys.
|
|
||||||
* When the billing event keys are loaded from SQL, they are loaded as asymmetric keys because the
|
|
||||||
* database columns that we load them from do not contain all of the information necessary to
|
|
||||||
* reconsitute the Ofy side of the key. In other cases, we restore the Ofy key during the
|
|
||||||
* hibernate {@link javax.persistence.PostLoad} method from the other fields of the object, but we
|
|
||||||
* have been unable to make this work with hibernate's internal persistence model in this case
|
|
||||||
* because the {@link GracePeriod}'s hash code is evaluated prior to these calls, and would be
|
|
||||||
* invalidated by changing the fields.
|
|
||||||
*/
|
|
||||||
private final synchronized void restoreOfyKeys() {
|
|
||||||
if (billingEventOneTime != null && !billingEventOneTime.maybeGetOfyKey().isPresent()) {
|
|
||||||
billingEventOneTime =
|
|
||||||
DomainBase.restoreOfyFrom(
|
|
||||||
Key.create(DomainBase.class, domainRepoId),
|
|
||||||
billingEventOneTime,
|
|
||||||
billingEventOneTimeHistoryId);
|
|
||||||
}
|
|
||||||
if (billingEventRecurring != null && !billingEventRecurring.maybeGetOfyKey().isPresent()) {
|
|
||||||
billingEventRecurring =
|
|
||||||
DomainBase.restoreOfyFrom(
|
|
||||||
Key.create(DomainBase.class, domainRepoId),
|
|
||||||
billingEventRecurring,
|
|
||||||
billingEventRecurringHistoryId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,9 +111,9 @@ public class AllocationToken extends BackupGroupRoot implements Buildable, Datas
|
||||||
@Nullable
|
@Nullable
|
||||||
@Index
|
@Index
|
||||||
@AttributeOverrides({
|
@AttributeOverrides({
|
||||||
@AttributeOverride(name = "domainRepoId", column = @Column(name = "redemption_domain_repo_id")),
|
@AttributeOverride(name = "repoId", column = @Column(name = "redemption_domain_repo_id")),
|
||||||
@AttributeOverride(
|
@AttributeOverride(
|
||||||
name = "domainHistoryId",
|
name = "historyRevisionId",
|
||||||
column = @Column(name = "redemption_domain_history_id"))
|
column = @Column(name = "redemption_domain_history_id"))
|
||||||
})
|
})
|
||||||
DomainHistoryVKey redemptionHistoryEntry;
|
DomainHistoryVKey redemptionHistoryEntry;
|
||||||
|
@ -192,8 +192,9 @@ public class AllocationToken extends BackupGroupRoot implements Buildable, Datas
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<VKey<HistoryEntry>> getRedemptionHistoryEntry() {
|
public Optional<VKey<? extends HistoryEntry>> getRedemptionHistoryEntry() {
|
||||||
return Optional.ofNullable(redemptionHistoryEntry);
|
return Optional.ofNullable(
|
||||||
|
redemptionHistoryEntry == null ? null : redemptionHistoryEntry.createDomainHistoryVKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRedeemed() {
|
public boolean isRedeemed() {
|
||||||
|
@ -291,9 +292,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable, Datas
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setRedemptionHistoryEntry(DomainHistoryVKey redemptionHistoryEntry) {
|
public Builder setRedemptionHistoryEntry(VKey<? extends HistoryEntry> redemptionHistoryEntry) {
|
||||||
getInstance().redemptionHistoryEntry =
|
|
||||||
checkArgumentNotNull(redemptionHistoryEntry, "Redemption history entry must not be null");
|
checkArgumentNotNull(redemptionHistoryEntry, "Redemption history entry must not be null");
|
||||||
|
getInstance().redemptionHistoryEntry =
|
||||||
|
DomainHistoryVKey.create(redemptionHistoryEntry.getOfyKey());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@ import google.registry.model.translators.CidrAddressBlockTranslatorFactory;
|
||||||
import google.registry.model.translators.CommitLogRevisionsTranslatorFactory;
|
import google.registry.model.translators.CommitLogRevisionsTranslatorFactory;
|
||||||
import google.registry.model.translators.CreateAutoTimestampTranslatorFactory;
|
import google.registry.model.translators.CreateAutoTimestampTranslatorFactory;
|
||||||
import google.registry.model.translators.CurrencyUnitTranslatorFactory;
|
import google.registry.model.translators.CurrencyUnitTranslatorFactory;
|
||||||
import google.registry.model.translators.DomainHistoryVKeyTranslatorFactory;
|
|
||||||
import google.registry.model.translators.DurationTranslatorFactory;
|
import google.registry.model.translators.DurationTranslatorFactory;
|
||||||
|
import google.registry.model.translators.EppHistoryVKeyTranslatorFactory;
|
||||||
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.UpdateAutoTimestampTranslatorFactory;
|
import google.registry.model.translators.UpdateAutoTimestampTranslatorFactory;
|
||||||
|
@ -128,7 +128,7 @@ public class ObjectifyService {
|
||||||
new CreateAutoTimestampTranslatorFactory(),
|
new CreateAutoTimestampTranslatorFactory(),
|
||||||
new CurrencyUnitTranslatorFactory(),
|
new CurrencyUnitTranslatorFactory(),
|
||||||
new DurationTranslatorFactory(),
|
new DurationTranslatorFactory(),
|
||||||
new DomainHistoryVKeyTranslatorFactory(),
|
new EppHistoryVKeyTranslatorFactory(),
|
||||||
new InetAddressTranslatorFactory(),
|
new InetAddressTranslatorFactory(),
|
||||||
new MoneyStringTranslatorFactory(),
|
new MoneyStringTranslatorFactory(),
|
||||||
new ReadableInstantUtcTranslatorFactory(),
|
new ReadableInstantUtcTranslatorFactory(),
|
||||||
|
|
|
@ -1,48 +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 com.google.appengine.api.datastore.Key;
|
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/** Translator factory for {@link DomainHistoryVKey}. */
|
|
||||||
public class DomainHistoryVKeyTranslatorFactory
|
|
||||||
extends AbstractSimpleTranslatorFactory<DomainHistoryVKey, Key> {
|
|
||||||
|
|
||||||
public DomainHistoryVKeyTranslatorFactory() {
|
|
||||||
super(DomainHistoryVKey.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
SimpleTranslator<DomainHistoryVKey, Key> createTranslator() {
|
|
||||||
return new SimpleTranslator<DomainHistoryVKey, Key>() {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public DomainHistoryVKey loadValue(@Nullable Key datastoreValue) {
|
|
||||||
return datastoreValue == null
|
|
||||||
? null
|
|
||||||
: DomainHistoryVKey.create(com.googlecode.objectify.Key.create(datastoreValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Key saveValue(@Nullable DomainHistoryVKey pojoValue) {
|
|
||||||
return pojoValue == null ? null : pojoValue.getOfyKey().getRaw();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
// 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.collect.ImmutableMap.toImmutableMap;
|
||||||
|
import static java.util.function.Function.identity;
|
||||||
|
|
||||||
|
import com.google.appengine.api.datastore.Key;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
|
||||||
|
import google.registry.persistence.DomainHistoryVKey;
|
||||||
|
import google.registry.persistence.EppHistoryVKey;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/** Translator factory for {@link EppHistoryVKey}. */
|
||||||
|
public class EppHistoryVKeyTranslatorFactory
|
||||||
|
extends AbstractSimpleTranslatorFactory<EppHistoryVKey, Key> {
|
||||||
|
|
||||||
|
public EppHistoryVKeyTranslatorFactory() {
|
||||||
|
super(EppHistoryVKey.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This map is used when we need to convert the raw Datastore key to its VKey instance. We have
|
||||||
|
// one dedicated VKey class, e.g. DomainHistoryVKey, for each such kind of entity, and we need
|
||||||
|
// a way to map the raw Datastore key to its VKey class. So, we use the kind path as the key of
|
||||||
|
// the map, and the kind path is created by concatenating all the kind strings in a raw Datastore
|
||||||
|
// key, e.g. the map key for ContactPollMessageVKey is "ContactResource/HistoryEntry/PollMessage".
|
||||||
|
@VisibleForTesting
|
||||||
|
static final ImmutableMap<String, Class<? extends EppHistoryVKey>> kindPathToVKeyClass =
|
||||||
|
ImmutableSet.of(DomainHistoryVKey.class, BillingEventVKey.class, BillingRecurrenceVKey.class)
|
||||||
|
.stream()
|
||||||
|
.collect(toImmutableMap(EppHistoryVKeyTranslatorFactory::getKindPath, identity()));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the kind path string for the given {@link Class}.
|
||||||
|
*
|
||||||
|
* <p>This method calls the getKindPath method on an instance of the given {@link Class} to get
|
||||||
|
* the kind path string.
|
||||||
|
*/
|
||||||
|
private static String getKindPath(Class<? extends EppHistoryVKey> clazz) {
|
||||||
|
try {
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
Object instance = constructor.newInstance();
|
||||||
|
Method getKindPathMethod = EppHistoryVKey.class.getDeclaredMethod("getKindPath");
|
||||||
|
getKindPathMethod.setAccessible(true);
|
||||||
|
return (String) getKindPathMethod.invoke(instance);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new IllegalStateException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SimpleTranslator<EppHistoryVKey, Key> createTranslator() {
|
||||||
|
return new SimpleTranslator<EppHistoryVKey, Key>() {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public EppHistoryVKey loadValue(@Nullable Key datastoreValue) {
|
||||||
|
if (datastoreValue == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
com.googlecode.objectify.Key<?> ofyKey =
|
||||||
|
com.googlecode.objectify.Key.create(datastoreValue);
|
||||||
|
String kindPath = EppHistoryVKey.createKindPath(ofyKey);
|
||||||
|
if (kindPathToVKeyClass.containsKey(kindPath)) {
|
||||||
|
Class<? extends EppHistoryVKey> vKeyClass = kindPathToVKeyClass.get(kindPath);
|
||||||
|
try {
|
||||||
|
Method createVKeyMethod =
|
||||||
|
vKeyClass.getDeclaredMethod("create", com.googlecode.objectify.Key.class);
|
||||||
|
return (EppHistoryVKey) createVKeyMethod.invoke(null, ofyKey);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Missing static method create(com.googlecode.objectify.Key) on " + vKeyClass);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new IllegalStateException("Error invoking createVKey on " + vKeyClass, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Missing EppHistoryVKey implementation for kind path: " + kindPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Key saveValue(@Nullable EppHistoryVKey pojoValue) {
|
||||||
|
return pojoValue == null ? null : pojoValue.createOfyKey().getRaw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
134
core/src/main/java/google/registry/persistence/BillingVKey.java
Normal file
134
core/src/main/java/google/registry/persistence/BillingVKey.java
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.persistence;
|
||||||
|
|
||||||
|
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
import google.registry.model.billing.BillingEvent.OneTime;
|
||||||
|
import google.registry.model.billing.BillingEvent.Recurring;
|
||||||
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.AttributeOverride;
|
||||||
|
import javax.persistence.AttributeOverrides;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/** Base class for {@link BillingEvent}'s {@link VKey}. */
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class BillingVKey<K> extends EppHistoryVKey<K, DomainBase> {
|
||||||
|
Long billingId;
|
||||||
|
|
||||||
|
// Hibernate requires a default constructor.
|
||||||
|
BillingVKey() {}
|
||||||
|
|
||||||
|
BillingVKey(String repoId, long historyRevisionId, long billingId) {
|
||||||
|
super(repoId, historyRevisionId);
|
||||||
|
this.billingId = billingId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key<HistoryEntry> createHistoryEntryKey() {
|
||||||
|
return Key.create(Key.create(DomainBase.class, repoId), HistoryEntry.class, historyRevisionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createSqlKey() {
|
||||||
|
return billingId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** VKey class for {@link BillingEvent.OneTime} that belongs to a {@link DomainBase} entity. */
|
||||||
|
@Embeddable
|
||||||
|
@AttributeOverrides({
|
||||||
|
@AttributeOverride(name = "repoId", column = @Column(name = "billing_event_domain_repo_id")),
|
||||||
|
@AttributeOverride(
|
||||||
|
name = "historyRevisionId",
|
||||||
|
column = @Column(name = "billing_event_history_id")),
|
||||||
|
@AttributeOverride(name = "billingId", column = @Column(name = "billing_event_id"))
|
||||||
|
})
|
||||||
|
public static class BillingEventVKey extends BillingVKey<OneTime> {
|
||||||
|
|
||||||
|
// Hibernate requires this default constructor
|
||||||
|
private BillingEventVKey() {}
|
||||||
|
|
||||||
|
private BillingEventVKey(String repoId, long historyRevisionId, long billingEventId) {
|
||||||
|
super(repoId, historyRevisionId, billingEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Key<OneTime> createOfyKey() {
|
||||||
|
return Key.create(createHistoryEntryKey(), BillingEvent.OneTime.class, billingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a {@link BillingEventVKey} instance from the given {@link Key} instance. */
|
||||||
|
public static BillingEventVKey create(@Nullable Key<BillingEvent.OneTime> ofyKey) {
|
||||||
|
if (ofyKey == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long billingEventId = ofyKey.getId();
|
||||||
|
long historyRevisionId = ofyKey.getParent().getId();
|
||||||
|
String repoId = ofyKey.getParent().getParent().getName();
|
||||||
|
return new BillingEventVKey(repoId, historyRevisionId, billingEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a {@link BillingEventVKey} instance from the given {@link VKey} instance. */
|
||||||
|
public static BillingEventVKey create(@Nullable VKey<BillingEvent.OneTime> vKey) {
|
||||||
|
return vKey == null ? null : create(vKey.getOfyKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** VKey class for {@link BillingEvent.Recurring} that belongs to a {@link DomainBase} entity. */
|
||||||
|
@Embeddable
|
||||||
|
@AttributeOverrides({
|
||||||
|
@AttributeOverride(
|
||||||
|
name = "repoId",
|
||||||
|
column = @Column(name = "billing_recurrence_domain_repo_id")),
|
||||||
|
@AttributeOverride(
|
||||||
|
name = "historyRevisionId",
|
||||||
|
column = @Column(name = "billing_recurrence_history_id")),
|
||||||
|
@AttributeOverride(name = "billingId", column = @Column(name = "billing_recurrence_id"))
|
||||||
|
})
|
||||||
|
public static class BillingRecurrenceVKey extends BillingVKey<Recurring> {
|
||||||
|
|
||||||
|
// Hibernate requires this default constructor
|
||||||
|
private BillingRecurrenceVKey() {}
|
||||||
|
|
||||||
|
private BillingRecurrenceVKey(String repoId, long historyRevisionId, long billingEventId) {
|
||||||
|
super(repoId, historyRevisionId, billingEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Key<Recurring> createOfyKey() {
|
||||||
|
return Key.create(createHistoryEntryKey(), BillingEvent.Recurring.class, billingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a {@link BillingRecurrenceVKey} instance from the given {@link Key} instance. */
|
||||||
|
public static BillingRecurrenceVKey create(@Nullable Key<BillingEvent.Recurring> ofyKey) {
|
||||||
|
if (ofyKey == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long billingEventId = ofyKey.getId();
|
||||||
|
long historyRevisionId = ofyKey.getParent().getId();
|
||||||
|
String repoId = ofyKey.getParent().getParent().getName();
|
||||||
|
return new BillingRecurrenceVKey(repoId, historyRevisionId, billingEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a {@link BillingRecurrenceVKey} instance from the given {@link VKey} instance. */
|
||||||
|
public static BillingRecurrenceVKey create(@Nullable VKey<BillingEvent.Recurring> vKey) {
|
||||||
|
return vKey == null ? null : create(vKey.getOfyKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,45 +18,44 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||||
|
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.domain.DomainHistory;
|
||||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.PostLoad;
|
|
||||||
|
|
||||||
/** {@link VKey} for {@link HistoryEntry} which parent is {@link DomainBase}. */
|
/** {@link VKey} for {@link HistoryEntry} which parent is {@link DomainBase}. */
|
||||||
@Embeddable
|
@Embeddable
|
||||||
public class DomainHistoryVKey extends VKey<HistoryEntry> {
|
public class DomainHistoryVKey extends EppHistoryVKey<HistoryEntry, DomainBase> {
|
||||||
|
|
||||||
private String domainRepoId;
|
|
||||||
|
|
||||||
private Long domainHistoryId;
|
|
||||||
|
|
||||||
// Hibernate requires a default constructor
|
// Hibernate requires a default constructor
|
||||||
private DomainHistoryVKey() {}
|
private DomainHistoryVKey() {}
|
||||||
|
|
||||||
private DomainHistoryVKey(String domainRepoId, long domainHistoryId) {
|
private DomainHistoryVKey(String repoId, long historyRevisionId) {
|
||||||
initWith(domainRepoId, domainHistoryId);
|
super(repoId, historyRevisionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostLoad
|
@Override
|
||||||
void postLoad() {
|
public Object createSqlKey() {
|
||||||
initWith(domainRepoId, domainHistoryId);
|
return new DomainHistoryId(repoId, historyRevisionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWith(String domainRepoId, long domainHistoryId) {
|
@Override
|
||||||
this.kind = HistoryEntry.class;
|
public Key<HistoryEntry> createOfyKey() {
|
||||||
this.ofyKey =
|
return Key.create(Key.create(DomainBase.class, repoId), HistoryEntry.class, historyRevisionId);
|
||||||
Key.create(Key.create(DomainBase.class, domainRepoId), HistoryEntry.class, domainHistoryId);
|
|
||||||
this.sqlKey = new DomainHistoryId(domainRepoId, domainHistoryId);
|
|
||||||
this.domainRepoId = domainRepoId;
|
|
||||||
this.domainHistoryId = domainHistoryId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates {@link DomainHistoryVKey} from the given {@link Key} instance. */
|
/** Creates {@link DomainHistoryVKey} from the given {@link Key} instance. */
|
||||||
public static DomainHistoryVKey create(Key<HistoryEntry> ofyKey) {
|
public static DomainHistoryVKey create(Key<? extends HistoryEntry> ofyKey) {
|
||||||
checkArgumentNotNull(ofyKey, "ofyKey must be specified");
|
checkArgumentNotNull(ofyKey, "ofyKey must be specified");
|
||||||
String domainRepoId = ofyKey.getParent().getName();
|
String repoId = ofyKey.getParent().getName();
|
||||||
long domainHistoryId = ofyKey.getId();
|
long historyRevisionId = ofyKey.getId();
|
||||||
return new DomainHistoryVKey(domainRepoId, domainHistoryId);
|
return new DomainHistoryVKey(repoId, historyRevisionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VKey<? extends HistoryEntry> createDomainHistoryVKey() {
|
||||||
|
return VKey.create(
|
||||||
|
DomainHistory.class,
|
||||||
|
createSqlKey(),
|
||||||
|
Key.create(Key.create(DomainBase.class, repoId), DomainHistory.class, historyRevisionId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.persistence;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.model.EppResource;
|
||||||
|
import google.registry.model.ImmutableObject;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for {@link VKey} which ofyKey has a {@link HistoryEntry} key as its parent and a key
|
||||||
|
* for EPP resource as its grandparent.
|
||||||
|
*
|
||||||
|
* <p>For such a {@link VKey}, we need to provide two type parameters to indicate the type of {@link
|
||||||
|
* VKey} itself and the type of EPP resource respectively.
|
||||||
|
*
|
||||||
|
* @param <K> type of the {@link VKey}
|
||||||
|
* @param <E> type of the EPP resource that the key belongs to
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
public abstract class EppHistoryVKey<K, E extends EppResource> extends ImmutableObject
|
||||||
|
implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3906580677709539818L;
|
||||||
|
|
||||||
|
String repoId;
|
||||||
|
|
||||||
|
Long historyRevisionId;
|
||||||
|
|
||||||
|
// Hibernate requires a default constructor.
|
||||||
|
EppHistoryVKey() {}
|
||||||
|
|
||||||
|
EppHistoryVKey(String repoId, long historyRevisionId) {
|
||||||
|
this.repoId = repoId;
|
||||||
|
this.historyRevisionId = historyRevisionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the kind path for the ofyKey in this instance.
|
||||||
|
*
|
||||||
|
* <p>This method is only used reflectively by {@link EppHistoryVKeyTranslatorFactory} to get the
|
||||||
|
* kind path for a given {@link EppHistoryVKey} instance so it is marked as a private method.
|
||||||
|
*
|
||||||
|
* @see #createKindPath(Key)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private String getKindPath() {
|
||||||
|
String eppKind = Key.getKind(new TypeInstantiator<E>(getClass()) {}.getExactType());
|
||||||
|
String keyKind = Key.getKind(new TypeInstantiator<K>(getClass()) {}.getExactType());
|
||||||
|
if (keyKind.equals(Key.getKind(HistoryEntry.class))) {
|
||||||
|
return createKindPath(eppKind, keyKind);
|
||||||
|
} else {
|
||||||
|
return createKindPath(eppKind, Key.getKind(HistoryEntry.class), keyKind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the kind path for the given ofyKey}.
|
||||||
|
*
|
||||||
|
* <p>The kind path is a string including all kind names(delimited by slash) of a hierarchical
|
||||||
|
* {@link Key}, e.g., the kind path for BillingEvent.OneTime is "DomainBase/HistoryEntry/OneTime".
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String createKindPath(@Nullable Key<?> ofyKey) {
|
||||||
|
if (ofyKey == null) {
|
||||||
|
return null;
|
||||||
|
} else if (ofyKey.getParent() == null) {
|
||||||
|
return ofyKey.getKind();
|
||||||
|
} else {
|
||||||
|
return createKindPath(createKindPath(ofyKey.getParent()), ofyKey.getKind());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createKindPath(String... kinds) {
|
||||||
|
return Joiner.on("/").join(kinds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a {@link VKey} from this instance. */
|
||||||
|
public VKey<K> createVKey() {
|
||||||
|
Class<K> vKeyType = new TypeInstantiator<K>(getClass()) {}.getExactType();
|
||||||
|
return VKey.create(vKeyType, createSqlKey(), createOfyKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Object createSqlKey();
|
||||||
|
|
||||||
|
public abstract Key<K> createOfyKey();
|
||||||
|
}
|
|
@ -71,7 +71,6 @@ import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import org.joda.money.CurrencyUnit;
|
import org.joda.money.CurrencyUnit;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -169,7 +168,7 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("abc123")
|
.setToken("abc123")
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey))
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||||
.build());
|
.build());
|
||||||
doCheckTest(
|
doCheckTest(
|
||||||
create(false, "example1.tld", "In use"),
|
create(false, "example1.tld", "In use"),
|
||||||
|
|
|
@ -162,7 +162,6 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.monitoring.whitebox.EppMetric;
|
import google.registry.monitoring.whitebox.EppMetric;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import google.registry.testing.ReplayExtension;
|
import google.registry.testing.ReplayExtension;
|
||||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
@ -505,7 +504,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("abc123")
|
.setToken("abc123")
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey))
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||||
.build());
|
.build());
|
||||||
clock.advanceOneMilli();
|
clock.advanceOneMilli();
|
||||||
EppException thrown =
|
EppException thrown =
|
||||||
|
@ -528,7 +527,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
HistoryEntry historyEntry =
|
HistoryEntry historyEntry =
|
||||||
ofy().load().type(HistoryEntry.class).ancestor(reloadResourceByForeignKey()).first().now();
|
ofy().load().type(HistoryEntry.class).ancestor(reloadResourceByForeignKey()).first().now();
|
||||||
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry())
|
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry())
|
||||||
.hasValue(DomainHistoryVKey.create(Key.create(historyEntry)));
|
.hasValue(HistoryEntry.createVKey(Key.create(historyEntry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1275,7 +1274,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
assertThat(reloadedToken.isRedeemed()).isTrue();
|
assertThat(reloadedToken.isRedeemed()).isTrue();
|
||||||
assertThat(reloadedToken.getRedemptionHistoryEntry())
|
assertThat(reloadedToken.getRedemptionHistoryEntry())
|
||||||
.hasValue(
|
.hasValue(
|
||||||
DomainHistoryVKey.create(
|
HistoryEntry.createVKey(
|
||||||
Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0))));
|
Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import google.registry.testing.AppEngineExtension;
|
import google.registry.testing.AppEngineExtension;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -198,7 +197,7 @@ class AllocationTokenFlowUtilsTest {
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("tokeN")
|
.setToken("tokeN")
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey))
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||||
.build());
|
.build());
|
||||||
assertThat(
|
assertThat(
|
||||||
flowUtils
|
flowUtils
|
||||||
|
|
|
@ -28,6 +28,7 @@ import com.googlecode.objectify.annotation.Parent;
|
||||||
import com.googlecode.objectify.annotation.Serialize;
|
import com.googlecode.objectify.annotation.Serialize;
|
||||||
import com.googlecode.objectify.cmd.Query;
|
import com.googlecode.objectify.cmd.Query;
|
||||||
import google.registry.model.ofy.Ofy;
|
import google.registry.model.ofy.Ofy;
|
||||||
|
import google.registry.persistence.EppHistoryVKey;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.testing.AppEngineExtension;
|
import google.registry.testing.AppEngineExtension;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
|
@ -173,7 +174,8 @@ public abstract class EntityTestCase {
|
||||||
}
|
}
|
||||||
// Descend into persisted ImmutableObject classes, but not anything else.
|
// Descend into persisted ImmutableObject classes, but not anything else.
|
||||||
if (ImmutableObject.class.isAssignableFrom(fieldClass)
|
if (ImmutableObject.class.isAssignableFrom(fieldClass)
|
||||||
&& !VKey.class.isAssignableFrom(fieldClass)) {
|
&& !VKey.class.isAssignableFrom(fieldClass)
|
||||||
|
&& !EppHistoryVKey.class.isAssignableFrom(fieldClass)) {
|
||||||
getAllPotentiallyIndexedFieldPaths(fieldClass).stream()
|
getAllPotentiallyIndexedFieldPaths(fieldClass).stream()
|
||||||
.map(subfield -> field.getName() + "." + subfield)
|
.map(subfield -> field.getName() + "." + subfield)
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|
|
@ -633,14 +633,13 @@ public class DomainBaseSqlTest {
|
||||||
"4-COM",
|
"4-COM",
|
||||||
END_OF_TIME,
|
END_OF_TIME,
|
||||||
"registrar1",
|
"registrar1",
|
||||||
createLegacyVKey(
|
oneTimeBillingEvent.createVKey()),
|
||||||
BillingEvent.OneTime.class, oneTimeBillingEvent.getId())),
|
|
||||||
GracePeriod.createForRecurring(
|
GracePeriod.createForRecurring(
|
||||||
GracePeriodStatus.AUTO_RENEW,
|
GracePeriodStatus.AUTO_RENEW,
|
||||||
"4-COM",
|
"4-COM",
|
||||||
END_OF_TIME,
|
END_OF_TIME,
|
||||||
"registrar1",
|
"registrar1",
|
||||||
createLegacyVKey(BillingEvent.Recurring.class, billEvent.getId())));
|
billEvent.createVKey()));
|
||||||
|
|
||||||
jpaTm().insert(contact);
|
jpaTm().insert(contact);
|
||||||
jpaTm().insert(contact2);
|
jpaTm().insert(contact2);
|
||||||
|
|
|
@ -875,16 +875,13 @@ public class DomainBaseTest extends EntityTestCase {
|
||||||
ImmutableSet<BillEventInfo> historyIds =
|
ImmutableSet<BillEventInfo> historyIds =
|
||||||
domain.getGracePeriods().stream()
|
domain.getGracePeriods().stream()
|
||||||
.map(
|
.map(
|
||||||
gp ->
|
gp -> new BillEventInfo(gp.getRecurringBillingEvent(), gp.getOneTimeBillingEvent()))
|
||||||
new BillEventInfo(
|
|
||||||
gp.getRecurringBillingEvent(), gp.billingEventRecurringHistoryId,
|
|
||||||
gp.getOneTimeBillingEvent(), gp.billingEventOneTimeHistoryId))
|
|
||||||
.collect(toImmutableSet());
|
.collect(toImmutableSet());
|
||||||
assertThat(historyIds)
|
assertThat(historyIds)
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
new BillEventInfo(null, null, oneTimeBillKey, historyEntryKey.getId()),
|
new BillEventInfo(null, oneTimeBillKey),
|
||||||
new BillEventInfo(recurringBillKey, historyEntryKey.getId(), null, null)));
|
new BillEventInfo(recurringBillKey, null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static class BillEventInfo extends ImmutableObject {
|
static class BillEventInfo extends ImmutableObject {
|
||||||
|
@ -895,13 +892,9 @@ public class DomainBaseTest extends EntityTestCase {
|
||||||
|
|
||||||
BillEventInfo(
|
BillEventInfo(
|
||||||
VKey<BillingEvent.Recurring> billingEventRecurring,
|
VKey<BillingEvent.Recurring> billingEventRecurring,
|
||||||
Long billingEventRecurringHistoryId,
|
VKey<BillingEvent.OneTime> billingEventOneTime) {
|
||||||
VKey<BillingEvent.OneTime> billingEventOneTime,
|
|
||||||
Long billingEventOneTimeHistoryId) {
|
|
||||||
this.billingEventRecurring = billingEventRecurring;
|
this.billingEventRecurring = billingEventRecurring;
|
||||||
this.billingEventRecurringHistoryId = billingEventRecurringHistoryId;
|
|
||||||
this.billingEventOneTime = billingEventOneTime;
|
this.billingEventOneTime = billingEventOneTime;
|
||||||
this.billingEventOneTimeHistoryId = billingEventOneTimeHistoryId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,11 +63,11 @@ public class GracePeriodTest {
|
||||||
recurringKey =
|
recurringKey =
|
||||||
VKey.create(
|
VKey.create(
|
||||||
Recurring.class,
|
Recurring.class,
|
||||||
12345,
|
12345L,
|
||||||
Key.create(
|
Key.create(
|
||||||
Key.create(Key.create(DomainBase.class, "1-TEST"), HistoryEntry.class, 343L),
|
Key.create(Key.create(DomainBase.class, "1-TEST"), HistoryEntry.class, 343L),
|
||||||
Recurring.class,
|
Recurring.class,
|
||||||
12345));
|
12345L));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,8 +80,6 @@ public class GracePeriodTest {
|
||||||
assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
|
assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
|
||||||
assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
|
assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
|
||||||
assertThat(gracePeriod.hasBillingEvent()).isTrue();
|
assertThat(gracePeriod.hasBillingEvent()).isTrue();
|
||||||
assertThat(gracePeriod.billingEventOneTimeHistoryId).isEqualTo(12345L);
|
|
||||||
assertThat(gracePeriod.billingEventRecurringHistoryId).isNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -96,8 +94,6 @@ public class GracePeriodTest {
|
||||||
assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
|
assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
|
||||||
assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
|
assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
|
||||||
assertThat(gracePeriod.hasBillingEvent()).isTrue();
|
assertThat(gracePeriod.hasBillingEvent()).isTrue();
|
||||||
assertThat(gracePeriod.billingEventOneTimeHistoryId).isNull();
|
|
||||||
assertThat(gracePeriod.billingEventRecurringHistoryId).isEqualTo(343L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -40,7 +40,6 @@ import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -86,7 +85,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("abc123Single")
|
.setToken("abc123Single")
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey))
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||||
.setDomainName("example.foo")
|
.setDomainName("example.foo")
|
||||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
|
@ -125,7 +124,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("abc123")
|
.setToken("abc123")
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey))
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
|
||||||
.setDomainName("blahdomain.foo")
|
.setDomainName("blahdomain.foo")
|
||||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||||
.build()),
|
.build()),
|
||||||
|
@ -231,7 +230,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("foobar")
|
.setToken("foobar")
|
||||||
.setTokenType(TokenType.UNLIMITED_USE)
|
.setTokenType(TokenType.UNLIMITED_USE)
|
||||||
.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey));
|
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey));
|
||||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, builder::build);
|
||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 google.registry.model.translators.EppHistoryVKeyTranslatorFactory.kindPathToVKeyClass;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/** Unit test for {@link EppHistoryVKeyTranslatorFactory}. */
|
||||||
|
class EppHistoryVKeyTranslatorFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void assertAllVKeyClassesHavingCreateFromOfyKeyMethod() {
|
||||||
|
kindPathToVKeyClass.forEach(
|
||||||
|
(kindPath, vKeyClass) -> {
|
||||||
|
try {
|
||||||
|
vKeyClass.getDeclaredMethod("create", com.googlecode.objectify.Key.class);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
fail("Missing static method create(com.googlecode.objectify.Key) on " + vKeyClass, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.persistence;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
|
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import com.googlecode.objectify.annotation.Entity;
|
||||||
|
import com.googlecode.objectify.annotation.Id;
|
||||||
|
import com.googlecode.objectify.annotation.Parent;
|
||||||
|
import google.registry.model.ImmutableObject;
|
||||||
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
import google.registry.model.common.EntityGroupRoot;
|
||||||
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||||
|
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
|
||||||
|
import google.registry.schema.replay.EntityTest.EntityForTesting;
|
||||||
|
import google.registry.testing.AppEngineExtension;
|
||||||
|
import google.registry.testing.DualDatabaseTest;
|
||||||
|
import google.registry.testing.TestOfyAndSql;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
/** Unit test for {@link BillingVKey}. */
|
||||||
|
@DualDatabaseTest
|
||||||
|
class BillingVKeyTest {
|
||||||
|
@RegisterExtension
|
||||||
|
final AppEngineExtension appEngine =
|
||||||
|
AppEngineExtension.builder()
|
||||||
|
.withDatastoreAndCloudSql()
|
||||||
|
.withOfyTestEntities(BillingVKeyTestEntity.class)
|
||||||
|
.withJpaUnitTestEntities(BillingVKeyTestEntity.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testRestoreSymmetricVKey() {
|
||||||
|
Key<HistoryEntry> domainHistoryKey =
|
||||||
|
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L);
|
||||||
|
|
||||||
|
Key<BillingEvent.OneTime> oneTimeOfyKey =
|
||||||
|
Key.create(domainHistoryKey, BillingEvent.OneTime.class, 100L);
|
||||||
|
VKey<BillingEvent.OneTime> oneTimeVKey =
|
||||||
|
VKey.create(BillingEvent.OneTime.class, 100L, oneTimeOfyKey);
|
||||||
|
|
||||||
|
Key<BillingEvent.Recurring> recurringOfyKey =
|
||||||
|
Key.create(domainHistoryKey, BillingEvent.Recurring.class, 200L);
|
||||||
|
VKey<BillingEvent.Recurring> recurringVKey =
|
||||||
|
VKey.create(BillingEvent.Recurring.class, 200L, recurringOfyKey);
|
||||||
|
|
||||||
|
BillingVKeyTestEntity original = new BillingVKeyTestEntity(oneTimeVKey, recurringVKey);
|
||||||
|
tm().transact(() -> tm().insert(original));
|
||||||
|
BillingVKeyTestEntity persisted = tm().transact(() -> tm().load(original.createVKey()));
|
||||||
|
|
||||||
|
assertThat(persisted).isEqualTo(original);
|
||||||
|
assertThat(persisted.getBillingEventVKey()).isEqualTo(oneTimeVKey);
|
||||||
|
assertThat(persisted.getBillingRecurrenceVKey()).isEqualTo(recurringVKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testHandleNullVKeyCorrectly() {
|
||||||
|
BillingVKeyTestEntity original = new BillingVKeyTestEntity(null, null);
|
||||||
|
tm().transact(() -> tm().insert(original));
|
||||||
|
BillingVKeyTestEntity persisted = tm().transact(() -> tm().load(original.createVKey()));
|
||||||
|
|
||||||
|
assertThat(persisted).isEqualTo(original);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EntityForTesting
|
||||||
|
@Entity
|
||||||
|
@javax.persistence.Entity
|
||||||
|
private static class BillingVKeyTestEntity extends ImmutableObject {
|
||||||
|
@Transient @Parent Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||||
|
|
||||||
|
@Id @javax.persistence.Id String id = "id";
|
||||||
|
|
||||||
|
BillingEventVKey billingEventVKey;
|
||||||
|
|
||||||
|
BillingRecurrenceVKey billingRecurrenceVKey;
|
||||||
|
|
||||||
|
BillingVKeyTestEntity() {}
|
||||||
|
|
||||||
|
BillingVKeyTestEntity(
|
||||||
|
VKey<BillingEvent.OneTime> onetime, VKey<BillingEvent.Recurring> recurring) {
|
||||||
|
this.billingEventVKey = BillingEventVKey.create(onetime);
|
||||||
|
this.billingRecurrenceVKey = BillingRecurrenceVKey.create(recurring);
|
||||||
|
}
|
||||||
|
|
||||||
|
VKey<BillingEvent.OneTime> getBillingEventVKey() {
|
||||||
|
return billingEventVKey.createVKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
VKey<BillingEvent.Recurring> getBillingRecurrenceVKey() {
|
||||||
|
return billingRecurrenceVKey.createVKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
VKey<BillingVKeyTestEntity> createVKey() {
|
||||||
|
return VKey.create(
|
||||||
|
BillingVKeyTestEntity.class, id, Key.create(parent, BillingVKeyTestEntity.class, id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,12 +56,17 @@ class DomainHistoryVKeyTest {
|
||||||
TestEntity persisted = tm().transact(() -> tm().load(original.createVKey()));
|
TestEntity persisted = tm().transact(() -> tm().load(original.createVKey()));
|
||||||
assertThat(persisted).isEqualTo(original);
|
assertThat(persisted).isEqualTo(original);
|
||||||
// Double check that the persisted.domainHistoryVKey is a symmetric VKey
|
// Double check that the persisted.domainHistoryVKey is a symmetric VKey
|
||||||
assertThat(persisted.domainHistoryVKey.getKind()).isEqualTo(HistoryEntry.class);
|
assertThat(persisted.domainHistoryVKey.createOfyKey())
|
||||||
assertThat(persisted.domainHistoryVKey.getOfyKey())
|
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L));
|
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L));
|
||||||
assertThat(persisted.domainHistoryVKey.getSqlKey())
|
assertThat(persisted.domainHistoryVKey.createSqlKey())
|
||||||
.isEqualTo(new DomainHistoryId("domainRepoId", 10L));
|
.isEqualTo(new DomainHistoryId("domainRepoId", 10L));
|
||||||
|
assertThat(persisted.domainHistoryVKey.createVKey())
|
||||||
|
.isEqualTo(
|
||||||
|
VKey.create(
|
||||||
|
HistoryEntry.class,
|
||||||
|
new DomainHistoryId("domainRepoId", 10L),
|
||||||
|
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOfyAndSql
|
@TestOfyAndSql
|
||||||
|
@ -69,9 +74,12 @@ class DomainHistoryVKeyTest {
|
||||||
Key<HistoryEntry> ofyKey =
|
Key<HistoryEntry> ofyKey =
|
||||||
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L);
|
Key.create(Key.create(DomainBase.class, "domainRepoId"), HistoryEntry.class, 10L);
|
||||||
DomainHistoryVKey domainHistoryVKey = DomainHistoryVKey.create(ofyKey);
|
DomainHistoryVKey domainHistoryVKey = DomainHistoryVKey.create(ofyKey);
|
||||||
assertThat(domainHistoryVKey.getKind()).isEqualTo(HistoryEntry.class);
|
assertThat(domainHistoryVKey.createOfyKey()).isEqualTo(ofyKey);
|
||||||
assertThat(domainHistoryVKey.getOfyKey()).isEqualTo(ofyKey);
|
assertThat(domainHistoryVKey.createSqlKey())
|
||||||
assertThat(domainHistoryVKey.getSqlKey()).isEqualTo(new DomainHistoryId("domainRepoId", 10L));
|
.isEqualTo(new DomainHistoryId("domainRepoId", 10L));
|
||||||
|
assertThat(domainHistoryVKey.createVKey())
|
||||||
|
.isEqualTo(
|
||||||
|
VKey.create(HistoryEntry.class, new DomainHistoryId("domainRepoId", 10L), ofyKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EntityForTesting
|
@EntityForTesting
|
||||||
|
|
|
@ -27,7 +27,6 @@ import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -173,7 +172,7 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
|
||||||
String domainToPersist = domainName != null ? domainName : "example.foo";
|
String domainToPersist = domainName != null ? domainName : "example.foo";
|
||||||
DomainBase domain = persistActiveDomain(domainToPersist);
|
DomainBase domain = persistActiveDomain(domainToPersist);
|
||||||
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1051L);
|
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1051L);
|
||||||
builder.setRedemptionHistoryEntry(DomainHistoryVKey.create(historyEntryKey));
|
builder.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey));
|
||||||
}
|
}
|
||||||
return persistResource(builder.build());
|
return persistResource(builder.build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,8 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.testing.DeterministicStringGenerator;
|
import google.registry.testing.DeterministicStringGenerator;
|
||||||
import google.registry.testing.DeterministicStringGenerator.Rule;
|
import google.registry.testing.DeterministicStringGenerator.Rule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
|
@ -313,7 +314,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
|
||||||
|
|
||||||
private AllocationToken createToken(
|
private AllocationToken createToken(
|
||||||
String token,
|
String token,
|
||||||
@Nullable DomainHistoryVKey redemptionHistoryEntry,
|
@Nullable VKey<? extends HistoryEntry> redemptionHistoryEntry,
|
||||||
@Nullable String domainName) {
|
@Nullable String domainName) {
|
||||||
AllocationToken.Builder builder =
|
AllocationToken.Builder builder =
|
||||||
new AllocationToken.Builder().setToken(token).setTokenType(SINGLE_USE);
|
new AllocationToken.Builder().setToken(token).setTokenType(SINGLE_USE);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.persistence.DomainHistoryVKey;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ class GetAllocationTokenCommandTest extends CommandTestCase<GetAllocationTokenCo
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setDomainName("fqqdn.tld")
|
.setDomainName("fqqdn.tld")
|
||||||
.setRedemptionHistoryEntry(
|
.setRedemptionHistoryEntry(
|
||||||
DomainHistoryVKey.create(Key.create(createHistoryEntryForEppResource(domain))))
|
HistoryEntry.createVKey(Key.create(createHistoryEntryForEppResource(domain))))
|
||||||
.build());
|
.build());
|
||||||
runCommand("foo");
|
runCommand("foo");
|
||||||
assertInStdout(
|
assertInStdout(
|
||||||
|
|
|
@ -278,8 +278,8 @@ class google.registry.model.domain.DomainHistory {
|
||||||
}
|
}
|
||||||
class google.registry.model.domain.GracePeriod {
|
class google.registry.model.domain.GracePeriod {
|
||||||
google.registry.model.domain.rgp.GracePeriodStatus type;
|
google.registry.model.domain.rgp.GracePeriodStatus type;
|
||||||
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$OneTime> billingEventOneTime;
|
google.registry.persistence.BillingVKey$BillingEventVKey billingEventOneTime;
|
||||||
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> billingEventRecurring;
|
google.registry.persistence.BillingVKey$BillingRecurrenceVKey billingEventRecurring;
|
||||||
java.lang.Long gracePeriodId;
|
java.lang.Long gracePeriodId;
|
||||||
java.lang.String clientId;
|
java.lang.String clientId;
|
||||||
org.joda.time.DateTime expirationTime;
|
org.joda.time.DateTime expirationTime;
|
||||||
|
@ -888,10 +888,17 @@ enum google.registry.model.transfer.TransferStatus {
|
||||||
SERVER_APPROVED;
|
SERVER_APPROVED;
|
||||||
SERVER_CANCELLED;
|
SERVER_CANCELLED;
|
||||||
}
|
}
|
||||||
class google.registry.persistence.DomainHistoryVKey {
|
class google.registry.persistence.BillingVKey$BillingEventVKey {
|
||||||
com.googlecode.objectify.Key<T> ofyKey;
|
java.lang.Long billingId;
|
||||||
java.lang.Class<? extends T> kind;
|
java.lang.Long historyRevisionId;
|
||||||
java.lang.Long domainHistoryId;
|
java.lang.String repoId;
|
||||||
java.lang.Object sqlKey;
|
}
|
||||||
java.lang.String domainRepoId;
|
class google.registry.persistence.BillingVKey$BillingRecurrenceVKey {
|
||||||
|
java.lang.Long billingId;
|
||||||
|
java.lang.Long historyRevisionId;
|
||||||
|
java.lang.String repoId;
|
||||||
|
}
|
||||||
|
class google.registry.persistence.DomainHistoryVKey {
|
||||||
|
java.lang.Long historyRevisionId;
|
||||||
|
java.lang.String repoId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,11 +261,11 @@ td.section {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="property_name">generated on</td>
|
<td class="property_name">generated on</td>
|
||||||
<td class="property_value">2020-12-05 00:29:03.934355</td>
|
<td class="property_value">2020-12-16 16:26:55.279224</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="property_name">last flyway file</td>
|
<td class="property_name">last flyway file</td>
|
||||||
<td id="lastFlywayFile" class="property_value">V81__drop_spec11_fkeys.sql</td>
|
<td id="lastFlywayFile" class="property_value">V82__add_columns_to_restore_symmetric_billing_vkey.sql</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -284,7 +284,7 @@ td.section {
|
||||||
generated on
|
generated on
|
||||||
</text>
|
</text>
|
||||||
<text text-anchor="start" x="4027.94" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
|
<text text-anchor="start" x="4027.94" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
|
||||||
2020-12-05 00:29:03.934355
|
2020-12-16 16:26:55.279224
|
||||||
</text>
|
</text>
|
||||||
<polygon fill="none" stroke="#888888" points="3940.44,-4 3940.44,-44 4205.44,-44 4205.44,-4 3940.44,-4" /> <!-- allocationtoken_a08ccbef -->
|
<polygon fill="none" stroke="#888888" points="3940.44,-4 3940.44,-44 4205.44,-44 4205.44,-4 3940.44,-4" /> <!-- allocationtoken_a08ccbef -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -79,3 +79,4 @@ V78__add_history_id_for_redemption_history_entry.sql
|
||||||
V79__drop_foreign_keys_on_pollmessage.sql
|
V79__drop_foreign_keys_on_pollmessage.sql
|
||||||
V80__defer_bill_event_key.sql
|
V80__defer_bill_event_key.sql
|
||||||
V81__drop_spec11_fkeys.sql
|
V81__drop_spec11_fkeys.sql
|
||||||
|
V82__add_columns_to_restore_symmetric_billing_vkey.sql
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
-- 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.
|
||||||
|
|
||||||
|
alter table "GracePeriod"
|
||||||
|
add column if not exists "billing_event_domain_repo_id" text;
|
||||||
|
alter table "GracePeriod"
|
||||||
|
add column if not exists "billing_recurrence_domain_repo_id" text;
|
||||||
|
alter table "GracePeriodHistory"
|
||||||
|
add column if not exists "billing_event_domain_repo_id" text;
|
||||||
|
alter table "GracePeriodHistory"
|
||||||
|
add column if not exists "billing_recurrence_domain_repo_id" text;
|
|
@ -398,8 +398,10 @@
|
||||||
grace_period_id int8 not null,
|
grace_period_id int8 not null,
|
||||||
billing_event_id int8,
|
billing_event_id int8,
|
||||||
billing_event_history_id int8,
|
billing_event_history_id int8,
|
||||||
|
billing_event_domain_repo_id text,
|
||||||
billing_recurrence_id int8,
|
billing_recurrence_id int8,
|
||||||
billing_recurrence_history_id int8,
|
billing_recurrence_history_id int8,
|
||||||
|
billing_recurrence_domain_repo_id text,
|
||||||
registrar_id text not null,
|
registrar_id text not null,
|
||||||
domain_repo_id text not null,
|
domain_repo_id text not null,
|
||||||
expiration_time timestamptz not null,
|
expiration_time timestamptz not null,
|
||||||
|
@ -411,8 +413,10 @@
|
||||||
grace_period_history_revision_id int8 not null,
|
grace_period_history_revision_id int8 not null,
|
||||||
billing_event_id int8,
|
billing_event_id int8,
|
||||||
billing_event_history_id int8,
|
billing_event_history_id int8,
|
||||||
|
billing_event_domain_repo_id text,
|
||||||
billing_recurrence_id int8,
|
billing_recurrence_id int8,
|
||||||
billing_recurrence_history_id int8,
|
billing_recurrence_history_id int8,
|
||||||
|
billing_recurrence_domain_repo_id text,
|
||||||
registrar_id text not null,
|
registrar_id text not null,
|
||||||
domain_repo_id text not null,
|
domain_repo_id text not null,
|
||||||
expiration_time timestamptz not null,
|
expiration_time timestamptz not null,
|
||||||
|
|
|
@ -533,7 +533,9 @@ CREATE TABLE public."GracePeriod" (
|
||||||
expiration_time timestamp with time zone NOT NULL,
|
expiration_time timestamp with time zone NOT NULL,
|
||||||
type text NOT NULL,
|
type text NOT NULL,
|
||||||
billing_event_history_id bigint,
|
billing_event_history_id bigint,
|
||||||
billing_recurrence_history_id bigint
|
billing_recurrence_history_id bigint,
|
||||||
|
billing_event_domain_repo_id text,
|
||||||
|
billing_recurrence_domain_repo_id text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -552,7 +554,9 @@ CREATE TABLE public."GracePeriodHistory" (
|
||||||
expiration_time timestamp with time zone NOT NULL,
|
expiration_time timestamp with time zone NOT NULL,
|
||||||
type text NOT NULL,
|
type text NOT NULL,
|
||||||
domain_history_revision_id bigint,
|
domain_history_revision_id bigint,
|
||||||
grace_period_id bigint NOT NULL
|
grace_period_id bigint NOT NULL,
|
||||||
|
billing_event_domain_repo_id text,
|
||||||
|
billing_recurrence_domain_repo_id text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue