Remove deprecated extra flow logic and TLD-specific pricing proxy

This also adds a domain update pricing hook to DomainPricingCustomLogic.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=142286755
This commit is contained in:
mcilwain 2016-12-16 12:31:08 -08:00 committed by Ben McIlwain
parent 348cea9d8d
commit f44557f34f
41 changed files with 494 additions and 1744 deletions

View file

@ -21,6 +21,7 @@ import google.registry.flows.SessionMetadata;
import google.registry.flows.domain.DomainPricingLogic;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainApplication;
import google.registry.model.eppinput.EppInput;
import google.registry.model.registry.Registry;
import org.joda.time.DateTime;
@ -36,11 +37,78 @@ public class DomainPricingCustomLogic extends BaseFlowCustomLogic {
super(eppInput, sessionMetadata);
}
/** A hook that customizes create price. */
/** A hook that customizes the application update price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeCreatePrice(CreatePriceParameters createPriceParameters)
public FeesAndCredits customizeApplicationUpdatePrice(
ApplicationUpdatePriceParameters priceParameters) throws EppException {
return priceParameters.feesAndCredits();
}
/** A hook that customizes the create price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeCreatePrice(CreatePriceParameters priceParameters)
throws EppException {
return createPriceParameters.feesAndCredits();
return priceParameters.feesAndCredits();
}
/** A hook that customizes the renew price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeRenewPrice(RenewPriceParameters priceParameters)
throws EppException {
return priceParameters.feesAndCredits();
}
/** A hook that customizes the restore price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeRestorePrice(RestorePriceParameters priceParameters)
throws EppException {
return priceParameters.feesAndCredits();
}
/** A hook that customizes the transfer price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeTransferPrice(TransferPriceParameters priceParameters)
throws EppException {
return priceParameters.feesAndCredits();
}
/** A hook that customizes the update price. */
@SuppressWarnings("unused")
public FeesAndCredits customizeUpdatePrice(UpdatePriceParameters priceParameters)
throws EppException {
return priceParameters.feesAndCredits();
}
/** A class to encapsulate parameters for a call to {@link #customizeApplicationUpdatePrice} . */
@AutoValue
public abstract static class ApplicationUpdatePriceParameters extends ImmutableObject {
public abstract FeesAndCredits feesAndCredits();
public abstract Registry registry();
public abstract DomainApplication domainApplication();
public abstract DateTime asOfDate();
public static Builder newBuilder() {
return new AutoValue_DomainPricingCustomLogic_ApplicationUpdatePriceParameters.Builder();
}
/** Builder for {@link ApplicationUpdatePriceParameters}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setFeesAndCredits(FeesAndCredits feesAndCredits);
public abstract Builder setRegistry(Registry registry);
public abstract Builder setDomainApplication(DomainApplication domainApplication);
public abstract Builder setAsOfDate(DateTime asOfDate);
public abstract ApplicationUpdatePriceParameters build();
}
}
/** A class to encapsulate parameters for a call to {@link #customizeCreatePrice} . */
@ -78,4 +146,140 @@ public class DomainPricingCustomLogic extends BaseFlowCustomLogic {
public abstract CreatePriceParameters build();
}
}
/** A class to encapsulate parameters for a call to {@link #customizeRenewPrice} . */
@AutoValue
public abstract static class RenewPriceParameters extends ImmutableObject {
public abstract FeesAndCredits feesAndCredits();
public abstract Registry registry();
public abstract InternetDomainName domainName();
public abstract DateTime asOfDate();
public abstract int years();
public static Builder newBuilder() {
return new AutoValue_DomainPricingCustomLogic_RenewPriceParameters.Builder();
}
/** Builder for {@link RenewPriceParameters}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setFeesAndCredits(FeesAndCredits feesAndCredits);
public abstract Builder setRegistry(Registry registry);
public abstract Builder setDomainName(InternetDomainName domainName);
public abstract Builder setAsOfDate(DateTime asOfDate);
public abstract Builder setYears(int years);
public abstract RenewPriceParameters build();
}
}
/** A class to encapsulate parameters for a call to {@link #customizeRestorePrice} . */
@AutoValue
public abstract static class RestorePriceParameters extends ImmutableObject {
public abstract FeesAndCredits feesAndCredits();
public abstract Registry registry();
public abstract InternetDomainName domainName();
public abstract DateTime asOfDate();
public static Builder newBuilder() {
return new AutoValue_DomainPricingCustomLogic_RestorePriceParameters.Builder();
}
/** Builder for {@link RestorePriceParameters}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setFeesAndCredits(FeesAndCredits feesAndCredits);
public abstract Builder setRegistry(Registry registry);
public abstract Builder setDomainName(InternetDomainName domainName);
public abstract Builder setAsOfDate(DateTime asOfDate);
public abstract RestorePriceParameters build();
}
}
/** A class to encapsulate parameters for a call to {@link #customizeTransferPrice} . */
@AutoValue
public abstract static class TransferPriceParameters extends ImmutableObject {
public abstract FeesAndCredits feesAndCredits();
public abstract Registry registry();
public abstract InternetDomainName domainName();
public abstract DateTime asOfDate();
public abstract int years();
public static Builder newBuilder() {
return new AutoValue_DomainPricingCustomLogic_TransferPriceParameters.Builder();
}
/** Builder for {@link TransferPriceParameters}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setFeesAndCredits(FeesAndCredits feesAndCredits);
public abstract Builder setRegistry(Registry registry);
public abstract Builder setDomainName(InternetDomainName domainName);
public abstract Builder setAsOfDate(DateTime asOfDate);
public abstract Builder setYears(int years);
public abstract TransferPriceParameters build();
}
}
/** A class to encapsulate parameters for a call to {@link #customizeUpdatePrice} . */
@AutoValue
public abstract static class UpdatePriceParameters extends ImmutableObject {
public abstract FeesAndCredits feesAndCredits();
public abstract Registry registry();
public abstract InternetDomainName domainName();
public abstract DateTime asOfDate();
public static Builder newBuilder() {
return new AutoValue_DomainPricingCustomLogic_UpdatePriceParameters.Builder();
}
/** Builder for {@link UpdatePriceParameters}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setFeesAndCredits(FeesAndCredits feesAndCredits);
public abstract Builder setRegistry(Registry registry);
public abstract Builder setDomainName(InternetDomainName domainName);
public abstract Builder setAsOfDate(DateTime asOfDate);
public abstract UpdatePriceParameters build();
}
}
}

View file

@ -37,7 +37,6 @@ import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
@ -177,7 +176,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
.setNameservers(command.getNameservers())
.setContacts(command.getContacts())
.build();
handleExtraFlowLogic(registry.getTldStr(), years, historyEntry, newDomain, now);
entitiesToSave.add(
newDomain,
buildApplicationHistory(application, now),
@ -363,22 +361,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
&& !matchesAnchorTenantReservation(domainName, authInfoToken);
}
private void handleExtraFlowLogic(
String tld, int years, HistoryEntry historyEntry, DomainResource newDomain, DateTime now)
throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainAllocateLogic(
newDomain,
clientId,
now,
years,
eppInput,
historyEntry);
}
}
private void enqueueTasks(AllocateCreateExtension allocateCreate, DomainResource newDomain) {
if (newDomain.shouldPublishToDns()) {
DnsQueue.create().addDomainRefreshTask(newDomain.getFullyQualifiedDomainName());

View file

@ -44,7 +44,6 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@ -260,8 +259,6 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
.build();
HistoryEntry historyEntry = buildHistory(newApplication.getRepoId(), command.getPeriod(), now);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
handleExtraFlowLogic(
registry.getTldStr(), command.getPeriod().getValue(), historyEntry, newApplication);
entitiesToSave.add(
newApplication,
historyEntry,
@ -383,21 +380,6 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
return responseExtensionsBuilder.build();
}
private void handleExtraFlowLogic(
String tld, int years, HistoryEntry historyEntry, DomainApplication newApplication)
throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalApplicationCreateLogic(
newApplication,
clientId,
years,
eppInput,
historyEntry);
}
}
/** Landrush applications are disallowed during sunrise. */
static class LandrushApplicationDisallowedDuringSunriseException
extends RequiredParameterMissingException {

View file

@ -108,21 +108,10 @@ public final class DomainApplicationDeleteFlow implements TransactionalFlow {
.setParent(Key.create(existingApplication))
.build();
updateForeignKeyIndexDeletionTime(newApplication);
handleExtraFlowLogic(tld, historyEntry, existingApplication, now);
ofy().save().<Object>entities(newApplication, historyEntry);
return responseBuilder.build();
}
private void handleExtraFlowLogic(String tld, HistoryEntry historyEntry,
DomainApplication existingApplication, DateTime now) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalApplicationDeleteLogic(
existingApplication, clientId, now, eppInput, historyEntry);
}
}
/** A sunrise application cannot be deleted during landrush. */
static class SunriseApplicationCannotBeDeletedInLandrushException
extends StatusProhibitsOperationException {

View file

@ -35,7 +35,6 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Info;
import google.registry.model.domain.flags.FlagsInfoResponseExtension;
import google.registry.model.domain.launch.LaunchInfoExtension;
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
import google.registry.model.eppcommon.AuthInfo;
@ -47,7 +46,6 @@ import google.registry.model.mark.Mark;
import google.registry.model.smd.EncodedSignedMark;
import google.registry.model.smd.SignedMark;
import google.registry.util.Clock;
import java.util.Set;
import javax.inject.Inject;
import org.joda.time.DateTime;
@ -136,16 +134,6 @@ public final class DomainApplicationInfoFlow implements Flow {
.setMarks(marksBuilder.build())
.build());
addSecDnsExtensionIfPresent(extensions, application.getDsData());
// If the TLD uses the flags extension, add it to the info response.
Optional<RegistryExtraFlowLogic> extraLogicManager =
RegistryExtraFlowLogicProxy.newInstanceForDomain(application);
if (extraLogicManager.isPresent()) {
Set<String> flags = extraLogicManager.get().getApplicationExtensionFlags(
application, clientId, now); // As-of date is always now for info commands.
if (!flags.isEmpty()) {
extensions.add(FlagsInfoResponseExtension.create(ImmutableList.copyOf(flags)));
}
}
return extensions.build();
}

View file

@ -55,7 +55,7 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Update;
@ -137,6 +137,7 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
@Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainApplicationUpdateFlow() {}
@Override
@ -160,7 +161,6 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
HistoryEntry historyEntry = buildHistory(existingApplication, now);
DomainApplication newApplication = updateApplication(existingApplication, command, now);
validateNewApplication(newApplication);
handleExtraFlowLogic(newApplication.getTld(), historyEntry, newApplication, now);
ofy().save().<ImmutableObject>entities(newApplication, historyEntry);
return responseBuilder.build();
}
@ -181,14 +181,14 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
throw new ApplicationStatusProhibitsUpdateException(
existingApplication.getApplicationStatus());
}
EppCommandOperations commandOperations = TldSpecificLogicProxy.getApplicationUpdatePrice(
Registry.get(tld), existingApplication, clientId, now, eppInput);
FeesAndCredits feesAndCredits =
pricingLogic.getApplicationUpdatePrice(Registry.get(tld), existingApplication, now);
FeeUpdateCommandExtension feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price
// mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because
// it throws an error if the name is premium, and we don't want to do that here.
Money totalCost = commandOperations.getTotalCost();
Money totalCost = feesAndCredits.getTotalCost();
if (feeUpdate != null) {
validateFeeChallenge(targetId, tld, now, feeUpdate, totalCost);
} else if (!totalCost.isZero()) {
@ -248,16 +248,6 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
validateNameserversCountForTld(newApplication.getTld(), newApplication.getNameservers().size());
}
private void handleExtraFlowLogic(String tld, HistoryEntry historyEntry,
DomainApplication newApplication, DateTime now) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalApplicationUpdateLogic(
newApplication, clientId, now, eppInput, historyEntry);
}
}
/** Application status prohibits this domain update. */
static class ApplicationStatusProhibitsUpdateException extends StatusProhibitsOperationException {
public ApplicationStatusProhibitsUpdateException(ApplicationStatus status) {

View file

@ -206,10 +206,8 @@ public final class DomainCheckFlow implements Flow {
feeCheckItem,
builder,
domainNames.get(domainName),
clientId,
feeCheck.getCurrency(),
now,
eppInput,
pricingLogic);
responseItems.add(builder.setDomainNameIfSupported(domainName).build());
}

View file

@ -156,7 +156,6 @@ public final class DomainDeleteFlow implements TransactionalFlow {
clientId)))
.setDeletePollMessage(Key.create(deletePollMessage));
}
handleExtraFlowLogic(existingDomain, historyEntry, now);
DomainResource newDomain = builder.build();
updateForeignKeyIndexDeletionTime(newDomain);
handlePendingTransferOnDelete(existingDomain, newDomain, now, historyEntry);
@ -233,17 +232,6 @@ public final class DomainDeleteFlow implements TransactionalFlow {
.build();
}
private void handleExtraFlowLogic(
DomainResource existingResource, HistoryEntry historyEntry, DateTime now)
throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingResource);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainDeleteLogic(
existingResource, clientId, now, eppInput, historyEntry);
}
}
@Nullable
private ImmutableList<FeeTransformResponseExtension> getResponseExtensions(
DomainResource existingDomain, DateTime now) {

View file

@ -22,7 +22,7 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.union;
import static google.registry.flows.EppXmlTransformer.unmarshal;
import static google.registry.flows.domain.TldSpecificLogicProxy.getMatchingLrpToken;
import static google.registry.flows.domain.DomainPricingLogic.getMatchingLrpToken;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.findTldForName;
@ -94,7 +94,6 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Add;
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.host.HostResource;
import google.registry.model.mark.Mark;
@ -586,10 +585,8 @@ public class DomainFlowUtils {
FeeQueryCommandExtensionItem feeRequest,
FeeQueryResponseExtensionItem.Builder<?, ?> builder,
InternetDomainName domain,
String clientId,
@Nullable CurrencyUnit topLevelCurrency,
DateTime currentDate,
EppInput eppInput,
DomainPricingLogic pricingLogic)
throws EppException {
DateTime now = currentDate;
@ -617,7 +614,7 @@ public class DomainFlowUtils {
.setCommand(feeRequest.getCommandName(), feeRequest.getPhase(), feeRequest.getSubphase())
.setCurrencyIfSupported(registry.getCurrency())
.setPeriod(feeRequest.getPeriod())
.setClass(TldSpecificLogicProxy.getFeeClass(domainNameString, now).orNull());
.setClass(pricingLogic.getFeeClass(domainNameString, now).orNull());
ImmutableList<Fee> fees = ImmutableList.of();
switch (feeRequest.getCommandName()) {
@ -633,26 +630,22 @@ public class DomainFlowUtils {
break;
case RENEW:
builder.setAvailIfSupported(true);
fees = TldSpecificLogicProxy.getRenewPrice(
registry, domainNameString, clientId, now, years, eppInput).getFees();
fees = pricingLogic.getRenewPrice(registry, domainNameString, now, years).getFees();
break;
case RESTORE:
if (years != 1) {
throw new RestoresAreAlwaysForOneYearException();
}
builder.setAvailIfSupported(true);
fees = TldSpecificLogicProxy.getRestorePrice(
registry, domainNameString, clientId, now, eppInput).getFees();
fees = pricingLogic.getRestorePrice(registry, domainNameString, now).getFees();
break;
case TRANSFER:
builder.setAvailIfSupported(true);
fees = TldSpecificLogicProxy.getTransferPrice(
registry, domainNameString, clientId, now, years, eppInput).getFees();
fees = pricingLogic.getTransferPrice(registry, domainNameString, now, years).getFees();
break;
case UPDATE:
builder.setAvailIfSupported(true);
fees = TldSpecificLogicProxy.getUpdatePrice(
registry, domainNameString, clientId, now, eppInput).getFees();
fees = pricingLogic.getUpdatePrice(registry, domainNameString, now).getFees();
break;
default:
throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName());

View file

@ -39,7 +39,6 @@ import google.registry.model.domain.DomainResource;
import google.registry.model.domain.DomainResource.Builder;
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
import google.registry.model.domain.fee06.FeeInfoResponseExtensionV06;
import google.registry.model.domain.flags.FlagsInfoResponseExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.rgp.RgpInfoExtension;
import google.registry.model.eppcommon.AuthInfo;
@ -48,7 +47,6 @@ import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.util.Clock;
import java.util.Set;
import javax.inject.Inject;
import org.joda.time.DateTime;
@ -149,26 +147,11 @@ public final class DomainInfoFlow implements Flow {
feeInfo,
builder,
InternetDomainName.from(targetId),
clientId,
null,
now,
eppInput,
pricingLogic);
extensions.add(builder.build());
}
// If the TLD uses the flags extension, add it to the info response.
Optional<RegistryExtraFlowLogic> extraLogicManager =
RegistryExtraFlowLogicProxy.newInstanceForDomain(domain);
if (extraLogicManager.isPresent()) {
Set<String> flags =
extraLogicManager
.get()
.getExtensionFlags(
domain, clientId, now); // As-of date is always now for info commands.
if (!flags.isEmpty()) {
extensions.add(FlagsInfoResponseExtension.create(ImmutableList.copyOf(flags)));
}
}
return extensions.build();
}
}

View file

@ -14,7 +14,7 @@
package google.registry.flows.domain;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static com.google.common.collect.Iterables.concat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
@ -28,20 +28,21 @@ import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.FlowScope;
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
import google.registry.flows.custom.DomainPricingCustomLogic;
import google.registry.flows.custom.DomainPricingCustomLogic.ApplicationUpdatePriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.CreatePriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.RenewPriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.RestorePriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.fee.BaseFee;
import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.Fee;
import google.registry.model.eppinput.EppInput;
import google.registry.model.registry.Registry;
import java.util.List;
import javax.inject.Inject;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
@ -62,11 +63,12 @@ public final class DomainPricingLogic {
/** A collection of fees and credits for a specific EPP transform. */
public static final class FeesAndCredits extends ImmutableObject {
private final CurrencyUnit currency;
private final ImmutableList<Fee> fees;
private final ImmutableList<Credit> credits;
/** Constructs an FeesAndCredits object. The arguments are sorted into fees and credits. */
/** Constructs a new instance. The currency must be the same across all fees and credits. */
public FeesAndCredits(CurrencyUnit currency, BaseFee... baseFees) {
this.currency = checkArgumentNotNull(currency, "Currency may not be null in FeesAndCredits.");
ImmutableList.Builder<Fee> feeBuilder = new ImmutableList.Builder<>();
@ -121,14 +123,19 @@ public final class DomainPricingLogic {
}
/** Returns the list of credits for the event. */
public List<Credit> getCredits() {
return nullToEmpty(credits);
public ImmutableList<Credit> getCredits() {
return ImmutableList.copyOf(nullToEmpty(credits));
}
/** Returns the currency for all fees in the event. */
public final CurrencyUnit getCurrency() {
return currency;
}
/** Returns all fees and credits for the event. */
public ImmutableList<BaseFee> getFeesAndCredits() {
return ImmutableList.copyOf(concat(getFees(), getCredits()));
}
}
/** Returns a new create price for the Pricer. */
@ -164,121 +171,97 @@ public final class DomainPricingLogic {
// TODO: (b/33000134) clean up the rest of the pricing calls.
/**
* Computes the renew fee or credit. This is called by other methods which use the renew fee
* (renew, restore, etc).
*/
static BaseFee getRenewFeeOrCredit(
Registry registry,
String domainName,
String clientId,
DateTime date,
int years,
EppInput eppInput)
throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
// TODO: Consider changing the method definition to have the domain passed in to begin with.
DomainResource domain = loadByForeignKey(DomainResource.class, domainName, date);
if (domain == null) {
throw new ResourceDoesNotExistException(DomainResource.class, domainName);
}
return extraFlowLogic.get().getRenewFeeOrCredit(domain, clientId, date, years, eppInput);
} else {
return Fee.create(getDomainRenewCost(domainName, date, years).getAmount(), FeeType.RENEW);
}
}
/** Returns a new renew price for the pricer. */
public static FeesAndCredits getRenewPrice(
@SuppressWarnings("unused")
public FeesAndCredits getRenewPrice(
Registry registry,
String domainName,
String clientId,
DateTime date,
int years,
EppInput eppInput)
int years)
throws EppException {
return new FeesAndCredits(
registry.getCurrency(),
getRenewFeeOrCredit(registry, domainName, clientId, date, years, eppInput));
Money renewCost = getDomainRenewCost(domainName, date, years);
return customLogic.customizeRenewPrice(
RenewPriceParameters.newBuilder()
.setFeesAndCredits(
new FeesAndCredits(
registry.getCurrency(), Fee.create(renewCost.getAmount(), FeeType.RENEW)))
.setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date)
.setYears(years)
.build());
}
/** Returns a new restore price for the pricer. */
public static FeesAndCredits getRestorePrice(
Registry registry, String domainName, String clientId, DateTime date, EppInput eppInput)
@SuppressWarnings("unused")
public FeesAndCredits getRestorePrice(Registry registry, String domainName, DateTime date)
throws EppException {
return new FeesAndCredits(
registry.getCurrency(),
getRenewFeeOrCredit(registry, domainName, clientId, date, 1, eppInput),
Fee.create(registry.getStandardRestoreCost().getAmount(), FeeType.RESTORE));
FeesAndCredits feesAndCredits =
new FeesAndCredits(
registry.getCurrency(),
Fee.create(getDomainRenewCost(domainName, date, 1).getAmount(), FeeType.RENEW),
Fee.create(registry.getStandardRestoreCost().getAmount(), FeeType.RESTORE));
return customLogic.customizeRestorePrice(
RestorePriceParameters.newBuilder()
.setFeesAndCredits(feesAndCredits)
.setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date)
.build());
}
/** Returns a new transfer price for the pricer. */
public static FeesAndCredits getTransferPrice(
public FeesAndCredits getTransferPrice(
Registry registry,
String domainName,
String clientId,
DateTime transferDate,
int years,
EppInput eppInput)
int years)
throws EppException {
// Currently, all transfer prices = renew prices, so just pass through.
return getRenewPrice(registry, domainName, clientId, transferDate, years, eppInput);
Money renewCost = getDomainRenewCost(domainName, transferDate, years);
return customLogic.customizeTransferPrice(
TransferPriceParameters.newBuilder()
.setFeesAndCredits(
new FeesAndCredits(
registry.getCurrency(), Fee.create(renewCost.getAmount(), FeeType.RENEW)))
.setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(transferDate)
.setYears(years)
.build());
}
/** Returns a new update price for the pricer. */
public static FeesAndCredits getUpdatePrice(
Registry registry, String domainName, String clientId, DateTime date, EppInput eppInput)
public FeesAndCredits getUpdatePrice(Registry registry, String domainName, DateTime date)
throws EppException {
CurrencyUnit currency = registry.getCurrency();
// If there is extra flow logic, it may specify an update price. Otherwise, there is none.
BaseFee feeOrCredit;
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
// TODO: Consider changing the method definition to have the domain passed in to begin with.
DomainResource domain = loadByForeignKey(DomainResource.class, domainName, date);
if (domain == null) {
throw new ResourceDoesNotExistException(DomainResource.class, domainName);
}
feeOrCredit = extraFlowLogic.get().getUpdateFeeOrCredit(domain, clientId, date, eppInput);
} else {
feeOrCredit = Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
}
return new FeesAndCredits(currency, feeOrCredit);
BaseFee feeOrCredit =
Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
return customLogic.customizeUpdatePrice(
UpdatePriceParameters.newBuilder()
.setFeesAndCredits(new FeesAndCredits(currency, feeOrCredit))
.setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date)
.build());
}
/** Returns a new domain application update price for the pricer. */
public static FeesAndCredits getApplicationUpdatePrice(
Registry registry,
DomainApplication application,
String clientId,
DateTime date,
EppInput eppInput)
throws EppException {
CurrencyUnit currency = registry.getCurrency();
// If there is extra flow logic, it may specify an update price. Otherwise, there is none.
BaseFee feeOrCredit;
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
feeOrCredit =
extraFlowLogic
.get()
.getApplicationUpdateFeeOrCredit(application, clientId, date, eppInput);
} else {
feeOrCredit = Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
}
return new FeesAndCredits(currency, feeOrCredit);
@SuppressWarnings("unused")
public FeesAndCredits getApplicationUpdatePrice(
Registry registry, DomainApplication application, DateTime date) throws EppException {
BaseFee feeOrCredit =
Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
return customLogic.customizeApplicationUpdatePrice(
ApplicationUpdatePriceParameters.newBuilder()
.setFeesAndCredits(new FeesAndCredits(registry.getCurrency(), feeOrCredit))
.setRegistry(registry)
.setDomainApplication(application)
.setAsOfDate(date)
.build());
}
/** Returns the fee class for a given domain and date. */
public static Optional<String> getFeeClass(String domainName, DateTime date) {
public Optional<String> getFeeClass(String domainName, DateTime date) {
return getDomainFeeClass(domainName, date);
}

View file

@ -49,7 +49,7 @@ import google.registry.flows.custom.DomainRenewFlowCustomLogic.BeforeResponsePar
import google.registry.flows.custom.DomainRenewFlowCustomLogic.BeforeResponseReturnData;
import google.registry.flows.custom.DomainRenewFlowCustomLogic.BeforeSaveParameters;
import google.registry.flows.custom.EntityChanges;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.OneTime;
@ -121,6 +121,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
@Inject HistoryEntry.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainRenewFlowCustomLogic customLogic;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainRenewFlow() {}
@Override
@ -137,10 +138,10 @@ public final class DomainRenewFlow implements TransactionalFlow {
int years = command.getPeriod().getValue();
FeeRenewCommandExtension feeRenew =
eppInput.getSingleExtension(FeeRenewCommandExtension.class);
EppCommandOperations commandOperations = TldSpecificLogicProxy.getRenewPrice(
Registry.get(existingDomain.getTld()), targetId, clientId, now, years, eppInput);
FeesAndCredits feesAndCredits =
pricingLogic.getRenewPrice(Registry.get(existingDomain.getTld()), targetId, now, years);
validateFeeChallenge(
targetId, existingDomain.getTld(), now, feeRenew, commandOperations.getTotalCost());
targetId, existingDomain.getTld(), now, feeRenew, feesAndCredits.getTotalCost());
customLogic.afterValidation(
AfterValidationParameters.newBuilder()
.setExistingDomain(existingDomain)
@ -161,7 +162,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
String tld = existingDomain.getTld();
// Bill for this explicit renew itself.
BillingEvent.OneTime explicitRenewEvent =
createRenewBillingEvent(tld, commandOperations.getTotalCost(), years, historyEntry, now);
createRenewBillingEvent(tld, feesAndCredits.getTotalCost(), years, historyEntry, now);
// Create a new autorenew billing event and poll message starting at the new expiration time.
BillingEvent.Recurring newAutorenewEvent = newAutorenewBillingEvent(existingDomain)
.setEventTime(newExpirationTime)
@ -173,13 +174,6 @@ public final class DomainRenewFlow implements TransactionalFlow {
.build();
// End the old autorenew billing event and poll message now. This may delete the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, now);
// Handle extra flow logic, if any.
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainRenewLogic(
existingDomain, clientId, now, years, eppInput, historyEntry);
}
DomainResource newDomain = existingDomain.asBuilder()
.setRegistrationExpirationTime(newExpirationTime)
.setAutorenewBillingEvent(Key.create(newAutorenewEvent))
@ -212,7 +206,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setDomain(newDomain)
.setResData(DomainRenewData.create(targetId, newExpirationTime))
.setResponseExtensions(
createResponseExtensions(commandOperations.getTotalCost(), feeRenew))
createResponseExtensions(feesAndCredits.getTotalCost(), feeRenew))
.build());
return responseBuilder
.setResData(responseData.resData())

View file

@ -42,7 +42,7 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.OneTime;
@ -114,6 +114,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
@Inject HistoryEntry.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainRestoreRequestFlow() {}
@Override
@ -128,11 +129,11 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
DateTime now = ofy().getTransactionTime();
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
Money restoreCost = Registry.get(existingDomain.getTld()).getStandardRestoreCost();
EppCommandOperations renewCommandOperations = TldSpecificLogicProxy.getRenewPrice(
Registry.get(existingDomain.getTld()), targetId, clientId, now, 1, eppInput);
FeesAndCredits feesAndCredits =
pricingLogic.getRenewPrice(Registry.get(existingDomain.getTld()), targetId, now, 1);
FeeUpdateCommandExtension feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
Money totalCost = renewCommandOperations.getTotalCost();
Money totalCost = feesAndCredits.getTotalCost();
verifyRestoreAllowed(command, existingDomain, restoreCost, totalCost, feeUpdate, now);
HistoryEntry historyEntry = buildHistory(existingDomain, now);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
@ -153,13 +154,6 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
.setAutorenewEndTime(END_OF_TIME)
.setParent(historyEntry)
.build();
// Handle extra flow logic, if any.
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainRestoreLogic(
existingDomain, clientId, now, eppInput, historyEntry);
}
DomainResource newDomain =
performRestore(existingDomain, newExpirationTime, autorenewEvent, autorenewPollMessage);
updateForeignKeyIndexDeletionTime(newDomain);

View file

@ -177,7 +177,6 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
newDomain.getTransferData(),
newExpirationTime,
historyEntry);
handleExtraFlowLogic(tld, historyEntry, newDomain);
ofy().save().<ImmutableObject>entities(
newDomain,
historyEntry,
@ -193,16 +192,4 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))
.build();
}
private void handleExtraFlowLogic(
String tld, HistoryEntry historyEntry, DomainResource newDomain) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainTransferApproveLogic(
newDomain,
clientId,
historyEntry);
}
}
}

View file

@ -92,7 +92,6 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
.build();
DomainResource newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now);
handleExtraFlowLogic(existingDomain.getTld(), historyEntry, existingDomain);
ofy().save().<ImmutableObject>entities(
newDomain,
historyEntry,
@ -108,16 +107,4 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
.build();
}
private void handleExtraFlowLogic(
String tld, HistoryEntry historyEntry, DomainResource existingDomain) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainTransferCancelLogic(
existingDomain,
clientId,
historyEntry);
}
}
}

View file

@ -90,7 +90,6 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
checkAllowedAccessToTld(clientId, existingDomain.getTld());
DomainResource newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now);
handleExtraFlowLogic(existingDomain.getTld(), historyEntry, existingDomain);
ofy().save().<ImmutableObject>entities(
newDomain,
historyEntry,
@ -106,16 +105,4 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
.build();
}
private void handleExtraFlowLogic(
String tld, HistoryEntry historyEntry, DomainResource existingDomain) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainTransferRejectLogic(
existingDomain,
clientId,
historyEntry);
}
}
}

View file

@ -176,7 +176,6 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
// that we've created in this flow and stored in pendingTransferData.
updateAutorenewRecurrenceEndTime(existingDomain, automaticTransferTime);
handleExtraFlowLogic(years, existingDomain, historyEntry, now);
DomainResource newDomain = existingDomain.asBuilder()
.setTransferData(pendingTransferData)
.addStatusValue(StatusValue.PENDING_TRANSFER)
@ -376,22 +375,6 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
.build();
}
private void handleExtraFlowLogic(
int years, DomainResource existingDomain, HistoryEntry historyEntry, DateTime now)
throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainTransferRequestLogic(
existingDomain,
gainingClientId,
now,
years,
eppInput,
historyEntry);
}
}
private DomainTransferResponse createResponse(
Period period, DomainResource existingDomain, DomainResource newDomain, DateTime now) {
// If the registration were approved this instant, this is what the new expiration would be,

View file

@ -56,7 +56,7 @@ import google.registry.flows.custom.DomainUpdateFlowCustomLogic.AfterValidationP
import google.registry.flows.custom.DomainUpdateFlowCustomLogic.BeforeSaveParameters;
import google.registry.flows.custom.EntityChanges;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
@ -146,7 +146,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
@Inject DnsQueue dnsQueue;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainUpdateFlowCustomLogic customLogic;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainUpdateFlow() {}
@Override
@ -179,7 +179,6 @@ public final class DomainUpdateFlow implements TransactionalFlow {
}
validateNewState(newDomain);
dnsQueue.addDomainRefreshTask(targetId);
handleExtraFlowLogic(existingDomain, historyEntry, now);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(newDomain, historyEntry);
Optional<BillingEvent.OneTime> statusUpdateBillingEvent =
@ -214,15 +213,13 @@ public final class DomainUpdateFlow implements TransactionalFlow {
}
String tld = existingDomain.getTld();
checkAllowedAccessToTld(clientId, tld);
EppCommandOperations commandOperations = TldSpecificLogicProxy.getUpdatePrice(
Registry.get(tld), targetId, clientId, now, eppInput);
FeeTransformCommandExtension feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price
// mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because
// it throws an error if the name is premium, and we don't want to do that here.
Money totalCost = commandOperations.getTotalCost();
FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(Registry.get(tld), targetId, now);
Money totalCost = feesAndCredits.getTotalCost();
if (feeUpdate != null) {
validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, totalCost);
} else if (!totalCost.isZero()) {
@ -352,14 +349,4 @@ public final class DomainUpdateFlow implements TransactionalFlow {
}
return Optional.absent();
}
private void handleExtraFlowLogic(
DomainResource existingDomain, HistoryEntry historyEntry, DateTime now) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
if (extraFlowLogic.isPresent()) {
extraFlowLogic.get().performAdditionalDomainUpdateLogic(
existingDomain, clientId, now, eppInput, historyEntry);
}
}
}

View file

@ -1,171 +0,0 @@
// Copyright 2016 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.flows.domain;
import google.registry.flows.EppException;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.fee.BaseFee;
import google.registry.model.eppinput.EppInput;
import google.registry.model.reporting.HistoryEntry;
import java.util.Set;
import org.joda.time.DateTime;
/**
* Interface for classes which provide extra registry logic for things like TLD-specific rules and
* discounts.
*/
@Deprecated
public interface RegistryExtraFlowLogic {
/** Gets the flags to be returned for application info commands. */
public Set<String> getApplicationExtensionFlags(
DomainApplication application, String clientId, DateTime asOfDate);
/** Gets the flags to be returned for domain info commands. */
public Set<String> getExtensionFlags(
DomainResource domainResource, String clientId, DateTime asOfDate);
/** Performs additional tasks required for an application create command. */
public void performAdditionalApplicationCreateLogic(
DomainApplication application,
String clientId,
int years,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for an application delete command. */
public void performAdditionalApplicationDeleteLogic(
DomainApplication application,
String clientId,
DateTime asOfDate,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Computes the expected application update fee. */
public BaseFee getApplicationUpdateFeeOrCredit(
DomainApplication application,
String clientId,
DateTime asOfDate,
EppInput eppInput) throws EppException;
/** Performs additional tasks required for an application update command. */
public void performAdditionalApplicationUpdateLogic(
DomainApplication application,
String clientId,
DateTime asOfDate,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for an allocate command. */
public void performAdditionalDomainAllocateLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
int years,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Computes the expected creation fee. */
public BaseFee getCreateFeeOrCredit(
String domainName,
String clientId,
DateTime asOfDate,
int years,
EppInput eppInput) throws EppException;
/** Performs additional tasks required for a create command. */
public void performAdditionalDomainCreateLogic(
DomainResource domain,
String clientId,
int years,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a delete command. */
public void performAdditionalDomainDeleteLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Computes the expected renewal fee. */
public BaseFee getRenewFeeOrCredit(
DomainResource domain,
String clientId,
DateTime asOfDate,
int years,
EppInput eppInput) throws EppException;
/** Performs additional tasks required for a renew command. */
public void performAdditionalDomainRenewLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
int years,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a restore command. */
public void performAdditionalDomainRestoreLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a domain transfer approve command. */
public void performAdditionalDomainTransferApproveLogic(
DomainResource domain,
String clientId,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a domain transfer cancel command. */
public void performAdditionalDomainTransferCancelLogic(
DomainResource domain,
String clientId,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a domain transfer reject command. */
public void performAdditionalDomainTransferRejectLogic(
DomainResource domain,
String clientId,
HistoryEntry historyEntry) throws EppException;
/** Performs additional tasks required for a transfer request command. */
public void performAdditionalDomainTransferRequestLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
int years,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
/** Computes the expected update fee. */
public BaseFee getUpdateFeeOrCredit(
DomainResource domain,
String clientId,
DateTime asOfDate,
EppInput eppInput) throws EppException;
/** Performs additional tasks required for an update command. */
public void performAdditionalDomainUpdateLogic(
DomainResource domain,
String clientId,
DateTime asOfDate,
EppInput eppInput,
HistoryEntry historyEntry) throws EppException;
}

View file

@ -1,64 +0,0 @@
// Copyright 2016 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.flows.domain;
import com.google.common.base.Optional;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandFailedException;
import google.registry.model.domain.DomainBase;
import google.registry.model.registry.Registry;
import java.util.HashMap;
import javax.annotation.Nullable;
/**
* Static class to return the correct {@link RegistryExtraFlowLogic} for a particular TLD.
* Eventually, this will probably be replaced with dependency injection, barring unforeseen
* complications.
*/
public class RegistryExtraFlowLogicProxy {
private static final HashMap<String, Class<? extends RegistryExtraFlowLogic>>
extraLogicOverrideMap = new HashMap<>();
public static void setOverride(
String tld, Class<? extends RegistryExtraFlowLogic> extraLogicClass) {
if (Registry.get(tld) == null) {
throw new IllegalArgumentException(tld + " does not exist");
}
extraLogicOverrideMap.put(tld, extraLogicClass);
}
public static <D extends DomainBase> Optional<RegistryExtraFlowLogic>
newInstanceForDomain(@Nullable D domain) throws EppException {
if (domain == null) {
return Optional.absent();
} else {
return newInstanceForTld(domain.getTld());
}
}
public static Optional<RegistryExtraFlowLogic>
newInstanceForTld(String tld) throws EppException {
if (extraLogicOverrideMap.containsKey(tld)) {
try {
return Optional.<RegistryExtraFlowLogic>of(
extraLogicOverrideMap.get(tld).getConstructor().newInstance());
} catch (ReflectiveOperationException ex) {
throw new CommandFailedException();
}
}
return Optional.absent();
}
}

View file

@ -1,314 +0,0 @@
// Copyright 2016 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.flows.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.fee.BaseFee;
import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.Fee;
import google.registry.model.eppinput.EppInput;
import google.registry.model.registry.Registry;
import java.util.List;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
/**
* Provides pricing, billing, and update logic, with call-outs that can be customized by providing
* implementations on a per-TLD basis.
*/
public final class TldSpecificLogicProxy {
/** A collection of fees and credits for a specific EPP transform. */
public static final class EppCommandOperations extends ImmutableObject {
private final CurrencyUnit currency;
private final ImmutableList<Fee> fees;
private final ImmutableList<Credit> credits;
/** Constructs an EppCommandOperations object using separate lists of fees and credits. */
EppCommandOperations(
CurrencyUnit currency, ImmutableList<Fee> fees, ImmutableList<Credit> credits) {
this.currency = checkArgumentNotNull(
currency, "Currency may not be null in EppCommandOperations.");
checkArgument(!fees.isEmpty(), "You must specify one or more fees.");
this.fees = checkArgumentNotNull(fees, "Fees may not be null in EppCommandOperations.");
this.credits =
checkArgumentNotNull(credits, "Credits may not be null in EppCommandOperations.");
}
/**
* Constructs an EppCommandOperations object. The arguments are sorted into fees and credits.
*/
EppCommandOperations(CurrencyUnit currency, BaseFee... feesAndCredits) {
this.currency = checkArgumentNotNull(
currency, "Currency may not be null in EppCommandOperations.");
ImmutableList.Builder<Fee> feeBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<Credit> creditBuilder = new ImmutableList.Builder<>();
for (BaseFee feeOrCredit : feesAndCredits) {
if (feeOrCredit instanceof Credit) {
creditBuilder.add((Credit) feeOrCredit);
} else {
feeBuilder.add((Fee) feeOrCredit);
}
}
this.fees = feeBuilder.build();
this.credits = creditBuilder.build();
}
private Money getTotalCostForType(FeeType type) {
Money result = Money.zero(currency);
checkArgumentNotNull(type);
for (Fee fee : fees) {
if (fee.getType() == type) {
result = result.plus(fee.getCost());
}
}
return result;
}
/** Returns the total cost of all fees and credits for the event. */
public Money getTotalCost() {
Money result = Money.zero(currency);
for (Fee fee : fees) {
result = result.plus(fee.getCost());
}
for (Credit credit : credits) {
result = result.plus(credit.getCost());
}
return result;
}
/** Returns the create cost for the event. */
public Money getCreateCost() {
return getTotalCostForType(FeeType.CREATE);
}
/** Returns the EAP cost for the event. */
public Money getEapCost() {
return getTotalCostForType(FeeType.EAP);
}
/** Returns the list of fees for the event. */
public ImmutableList<Fee> getFees() {
return fees;
}
/** Returns the list of credits for the event. */
public List<Credit> getCredits() {
return nullToEmpty(credits);
}
/** Returns the currency for all fees in the event. */
public final CurrencyUnit getCurrency() {
return currency;
}
}
private TldSpecificLogicProxy() {}
/** Returns a new create price for the Pricer. */
public static EppCommandOperations getCreatePrice(
Registry registry,
String domainName,
String clientId,
DateTime date,
int years,
EppInput eppInput) throws EppException {
CurrencyUnit currency = registry.getCurrency();
// Get the create cost, either from the extra flow logic or straight from PricingEngineProxy.
BaseFee createFeeOrCredit;
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
createFeeOrCredit = extraFlowLogic.get()
.getCreateFeeOrCredit(domainName, clientId, date, years, eppInput);
} else {
createFeeOrCredit =
Fee.create(getDomainCreateCost(domainName, date, years).getAmount(), FeeType.CREATE);
}
// Create fees for the cost and the EAP fee, if any.
Fee eapFee = registry.getEapFeeFor(date);
if (!eapFee.hasZeroCost()) {
return new EppCommandOperations(currency, createFeeOrCredit, eapFee);
} else {
return new EppCommandOperations(currency, createFeeOrCredit);
}
}
/**
* Computes the renew fee or credit. This is called by other methods which use the renew fee
* (renew, restore, etc).
*/
static BaseFee getRenewFeeOrCredit(
Registry registry,
String domainName,
String clientId,
DateTime date,
int years,
EppInput eppInput) throws EppException {
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
// TODO: Consider changing the method definition to have the domain passed in to begin with.
DomainResource domain = loadByForeignKey(DomainResource.class, domainName, date);
if (domain == null) {
throw new ResourceDoesNotExistException(DomainResource.class, domainName);
}
return
extraFlowLogic.get().getRenewFeeOrCredit(domain, clientId, date, years, eppInput);
} else {
return Fee.create(getDomainRenewCost(domainName, date, years).getAmount(), FeeType.RENEW);
}
}
/** Returns a new renew price for the pricer. */
public static EppCommandOperations getRenewPrice(
Registry registry,
String domainName,
String clientId,
DateTime date,
int years,
EppInput eppInput) throws EppException {
return new EppCommandOperations(
registry.getCurrency(),
getRenewFeeOrCredit(registry, domainName, clientId, date, years, eppInput));
}
/** Returns a new restore price for the pricer. */
public static EppCommandOperations getRestorePrice(
Registry registry,
String domainName,
String clientId,
DateTime date,
EppInput eppInput) throws EppException {
return new EppCommandOperations(
registry.getCurrency(),
getRenewFeeOrCredit(registry, domainName, clientId, date, 1, eppInput),
Fee.create(registry.getStandardRestoreCost().getAmount(), FeeType.RESTORE));
}
/** Returns a new transfer price for the pricer. */
public static EppCommandOperations getTransferPrice(
Registry registry,
String domainName,
String clientId,
DateTime transferDate,
int years,
EppInput eppInput) throws EppException {
// Currently, all transfer prices = renew prices, so just pass through.
return getRenewPrice(
registry, domainName, clientId, transferDate, years, eppInput);
}
/** Returns a new update price for the pricer. */
public static EppCommandOperations getUpdatePrice(
Registry registry,
String domainName,
String clientId,
DateTime date,
EppInput eppInput) throws EppException {
CurrencyUnit currency = registry.getCurrency();
// If there is extra flow logic, it may specify an update price. Otherwise, there is none.
BaseFee feeOrCredit;
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
// TODO: Consider changing the method definition to have the domain passed in to begin with.
DomainResource domain = loadByForeignKey(DomainResource.class, domainName, date);
if (domain == null) {
throw new ResourceDoesNotExistException(DomainResource.class, domainName);
}
feeOrCredit =
extraFlowLogic.get().getUpdateFeeOrCredit(domain, clientId, date, eppInput);
} else {
feeOrCredit = Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
}
return new EppCommandOperations(currency, feeOrCredit);
}
/** Returns a new domain application update price for the pricer. */
public static EppCommandOperations getApplicationUpdatePrice(
Registry registry,
DomainApplication application,
String clientId,
DateTime date,
EppInput eppInput) throws EppException {
CurrencyUnit currency = registry.getCurrency();
// If there is extra flow logic, it may specify an update price. Otherwise, there is none.
BaseFee feeOrCredit;
Optional<RegistryExtraFlowLogic> extraFlowLogic =
RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr());
if (extraFlowLogic.isPresent()) {
feeOrCredit = extraFlowLogic.get()
.getApplicationUpdateFeeOrCredit(application, clientId, date, eppInput);
} else {
feeOrCredit = Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
}
return new EppCommandOperations(currency, feeOrCredit);
}
/** Returns the fee class for a given domain and date. */
public static Optional<String> getFeeClass(String domainName, DateTime date) {
return getDomainFeeClass(domainName, date);
}
/**
* Checks whether an LRP token String maps to a valid {@link LrpTokenEntity} for the domain name's
* TLD, and return that entity (wrapped in an {@link Optional}) if one exists.
*
* <p>This method has no knowledge of whether or not an auth code (interpreted here as an LRP
* token) has already been checked against the reserved list for QLP (anchor tenant), as auth
* codes are used for both types of registrations.
*/
public static Optional<LrpTokenEntity> getMatchingLrpToken(
String lrpToken, InternetDomainName domainName) {
// Note that until the actual per-TLD logic is built out, what's being done here is a basic
// domain-name-to-assignee match.
if (!lrpToken.isEmpty()) {
LrpTokenEntity token = ofy().load().key(Key.create(LrpTokenEntity.class, lrpToken)).now();
if (token != null
&& token.getAssignee().equalsIgnoreCase(domainName.toString())
&& token.getRedemptionHistoryEntry() == null
&& token.getValidTlds().contains(domainName.parent().toString())) {
return Optional.of(token);
}
}
return Optional.<LrpTokenEntity>absent();
}
}