Support version 0.12 of the EPP Fee Extension

The corresponding version of the specification is 8.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=127968603
This commit is contained in:
Brian Mountford 2016-07-20 11:34:58 -07:00 committed by Justine Tunney
parent 38e7b07c93
commit b83b3b313f
56 changed files with 2505 additions and 13 deletions

View file

@ -20,6 +20,7 @@ import static com.google.common.io.Resources.getResource;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.FEE_0_11;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.FEE_0_12;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.FEE_0_6;
import static google.registry.model.registry.Registries.findTldForNameOrThrow;
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
@ -120,6 +121,7 @@ public class CheckApiAction implements Runnable {
if (available) {
FeeCheckResponseExtension<?> feeCheckResponseExtension =
(FeeCheckResponseExtension<?>) response.getFirstExtensionOfType(
FEE_0_12.getResponseExtensionClass(),
FEE_0_11.getResponseExtensionClass(),
FEE_0_6.getResponseExtensionClass());
if (feeCheckResponseExtension != null) {

View file

@ -57,6 +57,7 @@ public class EppXmlTransformer {
"secdns.xsd",
"fee06.xsd",
"fee11.xsd",
"fee12.xsd",
"metadata.xsd",
"mark.xsd",
"dsig.xsd",
@ -173,4 +174,3 @@ public class EppXmlTransformer {
}
}
}

View file

@ -17,6 +17,7 @@ package google.registry.flows;
import static com.google.common.base.Verify.verifyNotNull;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.registry.Registries.getTlds;
import static google.registry.util.CollectionUtils.nullToEmpty;
@ -28,7 +29,6 @@ import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.registrar.Registrar;
import google.registry.util.FormattingLogger;
@ -43,10 +43,7 @@ public abstract class LoggedInFlow extends Flow {
* A blacklist of service extension URIs that will cause an error if they are used without being
* declared on login.
*/
private static final ImmutableSet<String> UNDECLARED_URIS_BLACKLIST =
ImmutableSet.of(
ServiceExtension.FEE_0_6.getUri(),
ServiceExtension.FEE_0_11.getUri());
private static final ImmutableSet<String> UNDECLARED_URIS_BLACKLIST = FEE_EXTENSION_URIS;
/**
* The TLDs on which the logged-in registrar is allowed access domains.

View file

@ -40,6 +40,7 @@ import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import google.registry.model.domain.fee06.FeeDeleteResponseExtensionV06;
import google.registry.model.domain.fee11.FeeDeleteResponseExtensionV11;
import google.registry.model.domain.fee12.FeeDeleteResponseExtensionV12;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
@ -176,6 +177,9 @@ public class DomainDeleteFlow extends ResourceSyncDeleteFlow<DomainResource, Bui
@Nullable
private FeeTransformResponseExtension.Builder getDeleteResponseBuilder() {
Set<String> uris = nullToEmpty(sessionMetadata.getServiceExtensionUris());
if (uris.contains(ServiceExtension.FEE_0_12.getUri())) {
return new FeeDeleteResponseExtensionV12.Builder();
}
if (uris.contains(ServiceExtension.FEE_0_11.getUri())) {
return new FeeDeleteResponseExtensionV11.Builder();
}

View file

@ -15,6 +15,7 @@ FIELD_EXPOSERS = [
"domain/fee/FieldExposer.java",
"domain/fee06/FieldExposer.java",
"domain/fee11/FieldExposer.java",
"domain/fee12/FieldExposer.java",
"domain/launch/FieldExposer.java",
"domain/rgp/FieldExposer.java",
"domain/secdns/FieldExposer.java",

View file

@ -28,6 +28,11 @@ import google.registry.model.domain.fee11.FeeCreateCommandExtensionV11;
import google.registry.model.domain.fee11.FeeRenewCommandExtensionV11;
import google.registry.model.domain.fee11.FeeTransferCommandExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateCommandExtensionV11;
import google.registry.model.domain.fee12.FeeCheckCommandExtensionV12;
import google.registry.model.domain.fee12.FeeCreateCommandExtensionV12;
import google.registry.model.domain.fee12.FeeRenewCommandExtensionV12;
import google.registry.model.domain.fee12.FeeTransferCommandExtensionV12;
import google.registry.model.domain.fee12.FeeUpdateCommandExtensionV12;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import java.math.BigDecimal;
@ -48,36 +53,42 @@ public class Fee extends BaseFee {
Class<? extends FeeCheckCommandExtension<
? extends FeeCheckCommandExtensionItem,
? extends FeeCheckResponseExtension<?>>>>of(
FeeCheckCommandExtensionV12.class,
FeeCheckCommandExtensionV11.class,
FeeCheckCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeCreateCommandExtensionV12.class,
FeeCreateCommandExtensionV11.class,
FeeCreateCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeRenewCommandExtensionV12.class,
FeeRenewCommandExtensionV11.class,
FeeRenewCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeTransferCommandExtensionV12.class,
FeeTransferCommandExtensionV11.class,
FeeTransferCommandExtensionV06.class);
public static final ImmutableList<Class<? extends FeeTransformCommandExtension>>
FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER =
ImmutableList.<Class<? extends FeeTransformCommandExtension>>of(
FeeUpdateCommandExtensionV12.class,
FeeUpdateCommandExtensionV11.class,
FeeUpdateCommandExtensionV06.class);
public static final ImmutableSet<String>
FEE_EXTENSION_URIS =
ImmutableSet.<String>of(
ServiceExtension.FEE_0_12.getUri(),
ServiceExtension.FEE_0_11.getUri(),
ServiceExtension.FEE_0_6.getUri());
}

View file

@ -0,0 +1,126 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import com.google.common.base.Ascii;
import com.google.common.base.CharMatcher;
import com.google.common.base.Optional;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
import org.joda.time.DateTime;
/**
* An individual price check item in version 0.12 of the fee extension on domain check commands.
* Items look like:
*
* <fee:command name="renew" phase="sunrise" subphase="hello">
* <fee:period unit="y">1</fee:period>
* <fee:class>premium</fee:class>
* <fee:date>2017-05-17T13:22:21.0Z</fee:date>
* </fee:command>
*
* In a change from previous versions of the extension, items do not contain domain names; instead,
* the names from the non-extension check element are used.
*/
@XmlType(propOrder = {"period", "feeClass", "feeDate"})
public class FeeCheckCommandExtensionItemV12
extends ImmutableObject implements FeeCheckCommandExtensionItem {
/** The default validity period (if not specified) is 1 year for all operations. */
static final Period DEFAULT_PERIOD = Period.create(1, Period.Unit.YEARS);
@XmlAttribute(name = "name")
String commandName;
@XmlAttribute
String phase;
@XmlAttribute
String subphase;
@XmlElement
Period period;
@XmlElement(name = "class")
String feeClass;
@XmlElement(name = "date")
DateTime feeDate;
/** Version .12 does not support domain name or currency in fee extension items. */
@Override
public boolean isDomainNameSupported() {
return false;
}
@Override
public String getDomainName() {
throw new UnsupportedOperationException("Domain not supported");
}
@Override
public boolean isCurrencySupported() {
return false;
}
@Override
public CurrencyUnit getCurrency() {
throw new UnsupportedOperationException("Currency not supported");
}
@Override
public String getUnparsedCommandName() {
return commandName;
}
@Override
public CommandName getCommandName() {
// Require the xml string to be lowercase.
if (commandName != null && CharMatcher.javaLowerCase().matchesAllOf(commandName)) {
try {
return CommandName.valueOf(Ascii.toUpperCase(commandName));
} catch (IllegalArgumentException e) {
// Swallow this and return UNKNOWN below because there's no matching CommandName.
}
}
return CommandName.UNKNOWN;
}
@Override
public String getPhase() {
return phase;
}
@Override
public String getSubphase() {
return subphase;
}
@Override
public Period getPeriod() {
return Optional.fromNullable(period).or(DEFAULT_PERIOD);
}
@Override
public FeeCheckResponseExtensionItem.Builder createResponseBuilder() {
return new FeeCheckResponseExtensionItemV12.Builder();
}
}

View file

@ -0,0 +1,69 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeCheckCommandExtension;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/** Version 0.12 of the fee extension that may be present on domain check commands. */
@XmlRootElement(name = "check")
@XmlType(propOrder = {"currency", "items"})
public class FeeCheckCommandExtensionV12 extends ImmutableObject
implements FeeCheckCommandExtension<
FeeCheckCommandExtensionItemV12,
FeeCheckResponseExtensionV12> {
CurrencyUnit currency;
@Override
public boolean isCurrencySupported() {
return true;
}
@Override
public CurrencyUnit getCurrency() {
return currency;
}
@XmlElement(name = "command")
Set<FeeCheckCommandExtensionItemV12> items;
@Override
public ImmutableSet<FeeCheckCommandExtensionItemV12> getItems() {
return nullToEmptyImmutableCopy(items);
}
@Override
public FeeCheckResponseExtensionV12 createResponse(
ImmutableList<? extends FeeCheckResponseExtensionItem> items) {
ImmutableList.Builder<FeeCheckResponseExtensionItemV12> builder = new ImmutableList.Builder<>();
for (FeeCheckResponseExtensionItem item : items) {
if (item instanceof FeeCheckResponseExtensionItemV12) {
builder.add((FeeCheckResponseExtensionItemV12) item);
}
}
return FeeCheckResponseExtensionV12.create(currency, builder.build());
}
}

View file

@ -0,0 +1,105 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import static google.registry.util.CollectionUtils.forceEmptyToNull;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* The version 0.12 response command entity for a domain check on a single resource.
*/
@XmlType(propOrder = {"period", "fee", "feeClass"})
public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject {
/** The command that was checked. */
@XmlAttribute(name = "name")
String commandName;
/** The phase that was checked. */
@XmlAttribute
String phase;
/** The subphase that was checked. */
@XmlAttribute
String subphase;
/** The period that was checked. */
Period period;
/**
* The magnitude of the fee, in the specified units, with an optional description.
*
* <p>This is a list because a single operation can involve multiple fees.
*/
List<Fee> fee;
/**
* The type of the fee.
*
* <p>We will use "premium" for fees on premium names, and omit the field otherwise.
*/
@XmlElement(name = "class")
String feeClass;
public String getFeeClass() {
return feeClass;
}
/** Builder for {@link FeeCheckResponseExtensionItemCommandV12}. */
public static class Builder
extends GenericBuilder<FeeCheckResponseExtensionItemCommandV12, Builder> {
public Builder setCommandName(CommandName commandName) {
getInstance().commandName = Ascii.toLowerCase(commandName.name());
return this;
}
public Builder setPhase(String phase) {
getInstance().phase = phase;
return this;
}
public Builder setSubphase(String subphase) {
getInstance().subphase = subphase;
return this;
}
public Builder setPeriod(Period period) {
getInstance().period = period;
return this;
}
public Builder setFee(List<Fee> fees) {
getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees));
return this;
}
public Builder setClass(String feeClass) {
getInstance().feeClass = feeClass;
return this;
}
}
}

View file

@ -0,0 +1,115 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import static google.registry.util.CollectionUtils.forceEmptyToNull;
import com.google.common.collect.ImmutableList;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainObjectSpec;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import java.util.List;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/**
* The version 0.12 response for a domain check on a single resource.
*/
@XmlType(propOrder = {"object", "command"})
public class FeeCheckResponseExtensionItemV12
extends ImmutableObject implements FeeCheckResponseExtensionItem {
/** The domain that was checked. */
DomainObjectSpec object;
/** The command that was checked. */
FeeCheckResponseExtensionItemCommandV12 command;
@Override
public String getFeeClass() {
return command.getFeeClass();
}
/** Builder for {@link FeeCheckResponseExtensionItemV12}. */
public static class Builder
extends GenericBuilder<FeeCheckResponseExtensionItemV12, Builder>
implements FeeCheckResponseExtensionItem.Builder {
final FeeCheckResponseExtensionItemCommandV12.Builder commandBuilder;
Builder() {
super();
commandBuilder = new FeeCheckResponseExtensionItemCommandV12.Builder();
}
@Override
public Builder setCommand(CommandName commandName, String phase, String subphase) {
commandBuilder.setCommandName(commandName);
commandBuilder.setPhase(phase);
commandBuilder.setSubphase(subphase);
return this;
}
@Override
public Builder setPeriod(Period period) {
commandBuilder.setPeriod(period);
return this;
}
@Override
public Builder setFees(List<Fee> fees) {
commandBuilder.setFee(forceEmptyToNull(ImmutableList.copyOf(fees)));
return this;
}
@Override
public Builder setClass(String feeClass) {
commandBuilder.setClass(feeClass);
return this;
}
@Override
public Builder setDomainNameIfSupported(String name) {
getInstance().object = new DomainObjectSpec(name);
return this;
}
/** Version 0.12 does not support currency in check items. */
@Override
public Builder setCurrencyIfSupported(CurrencyUnit currency) {
return this;
}
@Override
public Builder setAvailIfSupported(boolean avail) {
return this;
}
@Override
public Builder setReasonIfSupported(String reason) {
return this;
}
@Override
public FeeCheckResponseExtensionItemV12 build() {
getInstance().command = commandBuilder.build();
return super.build();
}
}
}

View file

@ -0,0 +1,59 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.fee.FeeCheckResponseExtension;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.joda.money.CurrencyUnit;
/**
* An XML data object that represents version 0.12 of the fee extension that may be present on the
* response to EPP domain check commands.
*/
@XmlRootElement(name = "chkData")
@XmlType(propOrder = {"currency", "items"})
public class FeeCheckResponseExtensionV12
extends ImmutableObject implements FeeCheckResponseExtension<FeeCheckResponseExtensionItemV12> {
CurrencyUnit currency;
/** Check responses. */
@XmlElement(name = "cd")
ImmutableList<FeeCheckResponseExtensionItemV12> items;
@Override
public void setCurrencyIfSupported(CurrencyUnit currency) {
this.currency = currency;
}
@VisibleForTesting
@Override
public ImmutableList<FeeCheckResponseExtensionItemV12> getItems() {
return items;
}
static FeeCheckResponseExtensionV12
create(CurrencyUnit currency, ImmutableList<FeeCheckResponseExtensionItemV12> items) {
FeeCheckResponseExtensionV12 instance = new FeeCheckResponseExtensionV12();
instance.currency = currency;
instance.items = items;
return instance;
}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain create commands. */
@XmlRootElement(name = "create")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeCreateCommandExtensionV12
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeCreateResponseExtensionV12.Builder();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "creData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeCreateResponseExtensionV12 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeCreateResponseExtensionV12}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeCreateResponseExtensionV12, Builder> {}
}

View file

@ -0,0 +1,32 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain create commands.
*/
@XmlRootElement(name = "delData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeDeleteResponseExtensionV12 extends FeeTransformResponseExtensionImpl {
/** Builder for {@link FeeDeleteResponseExtensionV12}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeDeleteResponseExtensionV12, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain renew commands. */
@XmlRootElement(name = "renew")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeRenewCommandExtensionV12
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeRenewResponseExtensionV12.Builder();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain renew commands.
*/
@XmlRootElement(name = "renData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeRenewResponseExtensionV12 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeRenewResponseExtensionV12}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeRenewResponseExtensionV12, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain transfer requests. */
@XmlRootElement(name = "transfer")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeTransferCommandExtensionV12
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeTransferResponseExtensionV12.Builder();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain transfer requests.
*/
@XmlRootElement(name = "trnData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeTransferResponseExtensionV12 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeTransferResponseExtensionV12}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeTransferResponseExtensionV12, Builder> {}
}

View file

@ -0,0 +1,33 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformCommandExtension;
import google.registry.model.domain.fee.FeeTransformCommandExtensionImpl;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/** A fee extension that may be present on domain update commands. */
@XmlRootElement(name = "update")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeUpdateCommandExtensionV12
extends FeeTransformCommandExtensionImpl implements FeeTransformCommandExtension {
@Override
public FeeTransformResponseExtension.Builder createResponseBuilder() {
return new FeeUpdateResponseExtensionV12.Builder();
}
}

View file

@ -0,0 +1,31 @@
// Copyright 2016 The Domain Registry 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.domain.fee12;
import google.registry.model.domain.fee.FeeTransformResponseExtensionImpl;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* An XML data object that represents a fee extension that may be present on the response to EPP
* domain update commands.
*/
@XmlRootElement(name = "updData")
@XmlType(propOrder = {"currency", "fees", "credits"})
public class FeeUpdateResponseExtensionV12 extends FeeTransformResponseExtensionImpl {
/** A builder for {@link FeeUpdateResponseExtensionV12}. */
public static class Builder
extends FeeTransformResponseExtensionImpl.Builder<FeeUpdateResponseExtensionV12, Builder> {}
}

View file

@ -0,0 +1,29 @@
// Copyright 2016 The Domain Registry 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.
@XmlSchema(
namespace = "urn:ietf:params:xml:ns:fee-0.12",
xmlns = @XmlNs(prefix = "fee12", namespaceURI = "urn:ietf:params:xml:ns:fee-0.12"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class)
package google.registry.model.domain.fee12;
import google.registry.model.translators.CurrencyUnitAdapter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

View file

@ -26,6 +26,8 @@ import google.registry.model.domain.fee06.FeeCheckCommandExtensionV06;
import google.registry.model.domain.fee06.FeeCheckResponseExtensionV06;
import google.registry.model.domain.fee11.FeeCheckCommandExtensionV11;
import google.registry.model.domain.fee11.FeeCheckResponseExtensionV11;
import google.registry.model.domain.fee12.FeeCheckCommandExtensionV12;
import google.registry.model.domain.fee12.FeeCheckResponseExtensionV12;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.RgpUpdateExtension;
@ -54,6 +56,7 @@ public class ProtocolDefinition {
SECURE_DNS_1_1(SecDnsCreateExtension.class, null, true),
FEE_0_6(FeeCheckCommandExtensionV06.class, FeeCheckResponseExtensionV06.class, true),
FEE_0_11(FeeCheckCommandExtensionV11.class, FeeCheckResponseExtensionV11.class, true),
FEE_0_12(FeeCheckCommandExtensionV12.class, FeeCheckResponseExtensionV12.class, true),
ALLOCATE_1_0(AllocateCreateExtension.class, null, false),
METADATA_1_0(MetadataExtension.class, null, false);

View file

@ -36,6 +36,11 @@ import google.registry.model.domain.fee11.FeeCreateCommandExtensionV11;
import google.registry.model.domain.fee11.FeeRenewCommandExtensionV11;
import google.registry.model.domain.fee11.FeeTransferCommandExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateCommandExtensionV11;
import google.registry.model.domain.fee12.FeeCheckCommandExtensionV12;
import google.registry.model.domain.fee12.FeeCreateCommandExtensionV12;
import google.registry.model.domain.fee12.FeeRenewCommandExtensionV12;
import google.registry.model.domain.fee12.FeeTransferCommandExtensionV12;
import google.registry.model.domain.fee12.FeeUpdateCommandExtensionV12;
import google.registry.model.domain.launch.LaunchCheckExtension;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.launch.LaunchDeleteExtension;
@ -311,6 +316,12 @@ public class EppInput extends ImmutableObject {
@XmlElementRef(type = FeeRenewCommandExtensionV11.class),
@XmlElementRef(type = FeeTransferCommandExtensionV11.class),
@XmlElementRef(type = FeeUpdateCommandExtensionV11.class),
// fee extension version 0.12
@XmlElementRef(type = FeeCheckCommandExtensionV12.class),
@XmlElementRef(type = FeeCreateCommandExtensionV12.class),
@XmlElementRef(type = FeeRenewCommandExtensionV12.class),
@XmlElementRef(type = FeeTransferCommandExtensionV12.class),
@XmlElementRef(type = FeeUpdateCommandExtensionV12.class),
// other extensions
@XmlElementRef(type = LaunchCheckExtension.class),
@XmlElementRef(type = LaunchCreateExtension.class),

View file

@ -35,6 +35,12 @@ import google.registry.model.domain.fee11.FeeDeleteResponseExtensionV11;
import google.registry.model.domain.fee11.FeeRenewResponseExtensionV11;
import google.registry.model.domain.fee11.FeeTransferResponseExtensionV11;
import google.registry.model.domain.fee11.FeeUpdateResponseExtensionV11;
import google.registry.model.domain.fee12.FeeCheckResponseExtensionV12;
import google.registry.model.domain.fee12.FeeCreateResponseExtensionV12;
import google.registry.model.domain.fee12.FeeDeleteResponseExtensionV12;
import google.registry.model.domain.fee12.FeeRenewResponseExtensionV12;
import google.registry.model.domain.fee12.FeeTransferResponseExtensionV12;
import google.registry.model.domain.fee12.FeeUpdateResponseExtensionV12;
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
import google.registry.model.domain.launch.LaunchCreateResponseExtension;
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
@ -140,6 +146,12 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
@XmlElementRef(type = FeeRenewResponseExtensionV11.class),
@XmlElementRef(type = FeeTransferResponseExtensionV11.class),
@XmlElementRef(type = FeeUpdateResponseExtensionV11.class),
@XmlElementRef(type = FeeCheckResponseExtensionV12.class),
@XmlElementRef(type = FeeCreateResponseExtensionV12.class),
@XmlElementRef(type = FeeDeleteResponseExtensionV12.class),
@XmlElementRef(type = FeeRenewResponseExtensionV12.class),
@XmlElementRef(type = FeeTransferResponseExtensionV12.class),
@XmlElementRef(type = FeeUpdateResponseExtensionV12.class),
@XmlElementRef(type = LaunchCheckResponseExtension.class),
@XmlElementRef(type = LaunchCreateResponseExtension.class),
@XmlElementRef(type = LaunchInfoResponseExtension.class),

View file

@ -44,6 +44,7 @@ public class XjcXmlTransformer {
.put("smd", "smd.xsd")
.put("fee06", "fee06.xsd")
.put("fee11", "fee11.xsd")
.put("fee12", "fee12.xsd")
.put("launch", "launch.xsd")
.put("rde", "rde.xsd")
.put("rdeheader", "rde-header.xsd")

View file

@ -155,6 +155,15 @@
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings schemaLocation="fee12.xsd" node="/xsd:schema">
<schemaBindings>
<package name="google.registry.xjc.fee12"/>
<nameXmlTransform>
<elementName prefix="XjcFee12"/>
<typeName prefix="XjcFee12"/>
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings schemaLocation="launch.xsd" node="/xsd:schema">
<schemaBindings>
<package name="google.registry.xjc.launch"/>

View file

@ -1,3 +1,4 @@
#
# .'``'. ...
# :o o `....'` ;
@ -25,6 +26,7 @@ pkginfo_generated_files = [
"eppcom/package-info.java",
"fee06/package-info.java",
"fee11/package-info.java",
"fee12/package-info.java",
"host/package-info.java",
"iirdea/package-info.java",
"launch/package-info.java",
@ -208,6 +210,25 @@ xjc_generated_files = [
"fee11/XjcFee11TrnData.java",
"fee11/XjcFee11UpdData.java",
"fee11/XjcFee11Update.java",
"fee12/ObjectFactory.java",
"fee12/XjcFee12Check.java",
"fee12/XjcFee12ChkData.java",
"fee12/XjcFee12CommandCDType.java",
"fee12/XjcFee12CommandCheckType.java",
"fee12/XjcFee12CreData.java",
"fee12/XjcFee12Create.java",
"fee12/XjcFee12CreditType.java",
"fee12/XjcFee12DelData.java",
"fee12/XjcFee12FeeType.java",
"fee12/XjcFee12ObjectCDType.java",
"fee12/XjcFee12RenData.java",
"fee12/XjcFee12Renew.java",
"fee12/XjcFee12Transfer.java",
"fee12/XjcFee12TransformCommandType.java",
"fee12/XjcFee12TransformResultType.java",
"fee12/XjcFee12TrnData.java",
"fee12/XjcFee12UpdData.java",
"fee12/XjcFee12Update.java",
"host/ObjectFactory.java",
"host/XjcHostAddRemType.java",
"host/XjcHostAddrType.java",

View file

@ -35,6 +35,7 @@ create epp urn:ietf:params:xml:ns:epp-1.0
create eppcom urn:ietf:params:xml:ns:eppcom-1.0
create fee06 urn:ietf:params:xml:ns:fee-0.6
create fee11 urn:ietf:params:xml:ns:fee-0.11
create fee12 urn:ietf:params:xml:ns:fee-0.12
create host urn:ietf:params:xml:ns:host-1.0
create iirdea urn:ietf:params:xml:ns:iirdea-1.0
create launch urn:ietf:params:xml:ns:launch-1.0

View file

@ -24,6 +24,9 @@
@javax.xml.bind.annotation.XmlNs(
prefix = "fee11",
namespaceURI = "urn:ietf:params:xml:ns:fee-0.11"),
@javax.xml.bind.annotation.XmlNs(
prefix = "fee12",
namespaceURI = "urn:ietf:params:xml:ns:fee-0.12"),
@javax.xml.bind.annotation.XmlNs(
prefix = "host",
namespaceURI = "urn:ietf:params:xml:ns:host-1.0"),

View file

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:fee="urn:ietf:params:xml:ns:fee-0.12"
xmlns:eppcom="urn:ietf:params:xml:ns:eppcom-1.0"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
targetNamespace="urn:ietf:params:xml:ns:fee-0.12"
elementFormDefault="qualified">
<import namespace="urn:ietf:params:xml:ns:eppcom-1.0" />
<import namespace="urn:ietf:params:xml:ns:domain-1.0" />
<annotation>
<documentation>Extensible Provisioning Protocol
v1.0 extension schema for fee
information.</documentation>
</annotation>
<!--
Child elements found in EPP commands and responses
-->
<element name="check" type="fee:checkType" />
<element name="chkData" type="fee:chkDataType" />
<element name="create" type="fee:transformCommandType" />
<element name="creData" type="fee:transformResultType" />
<element name="renew" type="fee:transformCommandType" />
<element name="renData" type="fee:transformResultType" />
<element name="transfer" type="fee:transformCommandType" />
<element name="trnData" type="fee:transferResultType" />
<element name="update" type="fee:transformCommandType" />
<element name="updData" type="fee:transformResultType" />
<element name="delData" type="fee:transformResultType" />
<!--
client <check> command
-->
<complexType name="checkType">
<sequence>
<element name="currency"
type="fee:currencyType"
minOccurs="0" />
<element name="command"
type="fee:commandCheckType"
maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="commandCheckType">
<sequence>
<element name="period"
type="domain:periodType"
minOccurs="0" />
<element name="class"
type="token"
minOccurs="0" />
<element name="date"
type="dateTime"
minOccurs="0" />
</sequence>
<attribute name="name" type="fee:commandTypeValue" />
<attribute name="phase" type="token" />
<attribute name="subphase" type="token" />
</complexType>
<!--
server <check> result
-->
<complexType name="chkDataType">
<sequence>
<!--
Dialog is ongoing with Gavin Brown about this. His XSD has a
mandatory currency field. But what if the different domains being
checked have different currencies? I am trying to figure out what
he intends here. - Brian
-->
<element name="currency" type="fee:currencyType" minOccurs="0"/>
<element name="cd" type="fee:objectCDType"
maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="objectCDType">
<sequence>
<element name="object">
<complexType>
<sequence>
<any namespace="##other" processContents="lax"/>
</sequence>
</complexType>
</element>
<element name="command"
type="fee:commandCDType"
maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="commandCDType">
<sequence>
<element name="period"
type="domain:periodType"
minOccurs="0" maxOccurs="1" />
<element name="fee"
type="fee:feeType"
minOccurs="0" maxOccurs="unbounded" />
<element name="credit"
type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="class"
type="token"
minOccurs="0" />
<element name="reason"
type="token"
minOccurs="0" />
<element name="date"
type="dateTime"
minOccurs="0" />
<element name="notAfter"
type="dateTime"
minOccurs="0" />
</sequence>
<attribute name="avail" type="boolean" default="1" />
<attribute name="name" type="fee:commandTypeValue" />
<attribute name="phase" type="token" />
<attribute name="subphase" type="token" />
</complexType>
<!--
general transform (create, renew, update, transfer) command
-->
<complexType name="transformCommandType">
<sequence>
<element name="currency" type="fee:currencyType"
minOccurs="0" />
<element name="fee" type="fee:feeType"
maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<!--
general transform (create, renew, update, delete) result
-->
<complexType name="transformResultType">
<sequence>
<element name="currency" type="fee:currencyType" />
<element name="fee" type="fee:feeType"
minOccurs="0" maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="balance" type="fee:balanceType"
minOccurs="0" />
<element name="creditLimit" type="fee:creditLimitType"
minOccurs="0" />
</sequence>
</complexType>
<!--
transfer result
-->
<complexType name="transferResultType">
<sequence>
<element name="currency" type="fee:currencyType" />
<!-- only used op="query" responses -->
<element name="period" type="domain:periodType"
minOccurs="0" />
<element name="fee" type="fee:feeType"
maxOccurs="unbounded" />
<element name="credit" type="fee:creditType"
minOccurs="0" maxOccurs="unbounded" />
<element name="balance" type="fee:balanceType"
minOccurs="0" />
<element name="creditLimit" type="fee:creditLimitType"
minOccurs="0" />
</sequence>
</complexType>
<!--
common types
-->
<simpleType name="currencyType">
<restriction base="string">
<pattern value="[A-Z]{3}" />
</restriction>
</simpleType>
<simpleType name="commandTypeValue">
<restriction base="token">
<minLength value="3"/>
<maxLength value="16"/>
</restriction>
</simpleType>
<simpleType name="nonNegativeDecimal">
<restriction base="decimal">
<minInclusive value="0" />
</restriction>
</simpleType>
<simpleType name="negativeDecimal">
<restriction base="decimal">
<maxInclusive value="0" />
</restriction>
</simpleType>
<complexType name="feeType">
<simpleContent>
<extension base="fee:nonNegativeDecimal">
<attribute name="description"/>
<attribute name="refundable" type="boolean" />
<attribute name="grace-period" type="duration" />
<attribute name="applied" default="immediate">
<simpleType>
<restriction base="token">
<enumeration value="immediate" />
<enumeration value="delayed" />
</restriction>
</simpleType>
</attribute>
</extension>
</simpleContent>
</complexType>
<complexType name="creditType">
<simpleContent>
<extension base="fee:negativeDecimal">
<attribute name="description"/>
</extension>
</simpleContent>
</complexType>
<simpleType name="balanceType">
<restriction base="decimal" />
</simpleType>
<simpleType name="creditLimitType">
<restriction base="decimal" />
</simpleType>
</schema>