public enum InstantAccessOperationValue {
    PURCHASE("Purchase"),
    REVOKE("Revoke"),
    GETUSERID("GetUserId"),
    SUBSCRIPTIONGET("SubscriptionGet"),
    SUBSCRIPTIONACTIVATE("SubscriptionActivate"),
    SUBSCRIPTIONDEACTIVATE("SubscriptionDeactivate"),
    SUBSCRIPTIONUPDATE("SubscriptionUpdate");

    private String apiName;

    /**
     * @param apiName
     *            The string representation of the operation according to the API
     */
    InstantAccessOperationValue(String apiName) {
        this.apiName = apiName;
    }

    @JsonValue
    public String toJson() {
        return apiName;
    }

    @JsonCreator
    public static InstantAccessOperationValue fromJson(String text) {
        // ignore the case when deserializing
        return valueOf(text.toUpperCase());
    }
} @JsonIgnoreProperties(ignoreUnknown = true)
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public abstract class InstantAccessResponse<R extends Serializable> {
    protected R response;

    public R getResponse() {
        return response;
    }

    public void setResponse(R response) {
        this.response = response;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((response == null) ? 0 : response.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        InstantAccessResponse other = (InstantAccessResponse) obj;
        if (response == null) {
            if (other.response != null) {
                return false;
            }
        } else if (!response.equals(other.response)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("response", response).toString();
    }
} public class SubscriptionResponse extends InstantAccessResponse<SubscriptionResponseValue> {
} public class FulfillPurchaseRequest extends InstantAccessRequest {
    private String purchaseToken;
    private String userId;
    private String productId;
    private String reason;

    @Override
    public FulfillPurchaseRequest setOperation(InstantAccessOperationValue operation) {
        this.operation = operation;
        return this;
    }

    public String getPurchaseToken() {
        return purchaseToken;
    }

    public FulfillPurchaseRequest setPurchaseToken(String purchaseToken) {
        this.purchaseToken = purchaseToken;
        return this;
    }

    public String getUserId() {
        return userId;
    }

    public FulfillPurchaseRequest setUserId(String userId) {
        this.userId = userId;
        return this;
    }

    public String getProductId() {
        return productId;
    }

    public FulfillPurchaseRequest setProductId(String productId) {
        this.productId = productId;
        return this;
    }

    public String getReason() {
        return reason;
    }

    public FulfillPurchaseRequest setReason(String reason) {
        this.reason = reason;
        return this;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((purchaseToken == null) ? 0 : purchaseToken.hashCode());
        result = prime * result + ((operation == null) ? 0 : operation.hashCode());
        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
        result = prime * result + ((productId == null) ? 0 : productId.hashCode());
        result = prime * result + ((reason == null) ? 0 : reason.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FulfillPurchaseRequest other = (FulfillPurchaseRequest) obj;
        if (purchaseToken == null) {
            if (other.purchaseToken != null) {
                return false;
            }
        } else if (!purchaseToken.equals(other.purchaseToken)) {
            return false;
        }

        if (operation == null) {
            if (other.operation != null) {
                return false;
            }
        } else if (!operation.equals(other.operation)) {
            return false;
        }

        if (userId == null) {
            if (other.userId != null) {
                return false;
            }
        } else if (!userId.equals(other.userId)) {
            return false;
        }

        if (productId == null) {
            if (other.productId != null) {
                return false;
            }
        } else if (!productId.equals(other.productId)) {
            return false;
        }

        if (reason == null) {
            if (other.reason != null) {
                return false;
            }
        } else if (!reason.equals(other.reason)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation)
                .append("reason", reason).append("productId", productId).append("userId", userId)
                .append("purchaseToken", purchaseToken).toString();
    }
} public class FulfillPurchaseResponse extends InstantAccessResponse<FulfillPurchaseResponseValue> {
} public class RevokePurchaseRequest extends InstantAccessRequest {
    private String purchaseToken;
    private String userId;
    private String productId;
    private String reason;

    @Override
    public RevokePurchaseRequest setOperation(InstantAccessOperationValue operation) {
        this.operation = operation;
        return this;
    }

    public String getPurchaseToken() {
        return purchaseToken;
    }

    public RevokePurchaseRequest setPurchaseToken(String purchaseToken) {
        this.purchaseToken = purchaseToken;
        return this;
    }

    public String getUserId() {
        return userId;
    }

    public RevokePurchaseRequest setUserId(String userId) {
        this.userId = userId;
        return this;
    }

    public String getProductId() {
        return productId;
    }

    public RevokePurchaseRequest setProductId(String productId) {
        this.productId = productId;
        return this;
    }

    public String getReason() {
        return reason;
    }

    public RevokePurchaseRequest setReason(String reason) {
        this.reason = reason;
        return this;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((operation == null) ? 0 : operation.hashCode());
        result = prime * result + ((productId == null) ? 0 : productId.hashCode());
        result = prime * result + ((purchaseToken == null) ? 0 : purchaseToken.hashCode());
        result = prime * result + ((reason == null) ? 0 : reason.hashCode());
        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        RevokePurchaseRequest other = (RevokePurchaseRequest) obj;
        if (operation == null) {
            if (other.operation != null) {
                return false;
            }
        } else if (!operation.equals(other.operation)) {
            return false;
        }
        if (productId == null) {
            if (other.productId != null) {
                return false;
            }
        } else if (!productId.equals(other.productId)) {
            return false;
        }
        if (purchaseToken == null) {
            if (other.purchaseToken != null) {
                return false;
            }
        } else if (!purchaseToken.equals(other.purchaseToken)) {
            return false;
        }
        if (reason == null) {
            if (other.reason != null) {
                return false;
            }
        } else if (!reason.equals(other.reason)) {
            return false;
        }
        if (userId == null) {
            if (other.userId != null) {
                return false;
            }
        } else if (!userId.equals(other.userId)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation)
                .append("reason", reason).append("productId", productId).append("userId", userId)
                .append("purchaseToken", purchaseToken).toString();
    }
} public class RevokePurchaseResponse extends InstantAccessResponse<RevokePurchaseResponseValue> {
} @Deprecated
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class SubscriptionActivateRequest extends SubscriptionRequest {

    protected String productId;
    protected String userId;
    protected Integer numberOfSubscriptionsInGroup;
    protected String subscriptionGroupId;

    @Override
    public SubscriptionActivateRequest setOperation(InstantAccessOperationValue operationValue) {
        this.operation = operationValue;
        return this;
    }

    public String getProductId() {
        return productId;
    }

    public SubscriptionActivateRequest setProductId(String productId) {
        this.productId = productId;
        return this;
    }

    @Override
    public SubscriptionActivateRequest setSubscriptionId(String subscriptionId) {
        this.subscriptionId = subscriptionId;
        return this;
    }

    public String getUserId() {
        return userId;
    }

    public SubscriptionActivateRequest setUserId(String userId) {
        this.userId = userId;
        return this;
    }

    public Integer getNumberOfSubscriptionsInGroup() {
        return numberOfSubscriptionsInGroup;
    }

    public SubscriptionActivateRequest setNumberOfSubscriptionsInGroup(Integer numberOfSubscriptionsInGroup) {
        this.numberOfSubscriptionsInGroup = numberOfSubscriptionsInGroup;
        return this;
    }

    public String getSubscriptionGroupId() {
        return subscriptionGroupId;
    }

    public SubscriptionActivateRequest setSubscriptionGroupId(String subscriptionGroupId) {
        this.subscriptionGroupId = subscriptionGroupId;
        return this;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof SubscriptionActivateRequest)) return false;
        if (!super.equals(o)) return false;

        final SubscriptionActivateRequest that = (SubscriptionActivateRequest) o;

        if (productId != null ? !productId.equals(that.productId) : that.productId != null) return false;
        if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
        if (numberOfSubscriptionsInGroup != null ? !numberOfSubscriptionsInGroup.equals(that.numberOfSubscriptionsInGroup) : that.numberOfSubscriptionsInGroup != null)
            return false;
        if (subscriptionGroupId != null ? !subscriptionGroupId.equals(that.subscriptionGroupId) : that.subscriptionGroupId != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (productId != null ? productId.hashCode() : 0);
        result = 31 * result + (userId != null ? userId.hashCode() : 0);
        result = 31 * result + (numberOfSubscriptionsInGroup != null ? numberOfSubscriptionsInGroup.hashCode() : 0);
        result = 31 * result + (subscriptionGroupId != null ? subscriptionGroupId.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
                .append("operation", operation)
                .append("subscriptionId", subscriptionId)
                .append("productId", productId)
                .append("userId", userId)
                .append("numberOfSubscriptionsInGroup", numberOfSubscriptionsInGroup)
                .append("subscriptionGroupId", subscriptionGroupId)
                .toString();
    }
} @Deprecated
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class SubscriptionDeactivateRequest extends SubscriptionRequest {

    protected SubscriptionReasonValue reason;
    protected SubscriptionPeriodValue period;

    @Override
    public SubscriptionDeactivateRequest setOperation(InstantAccessOperationValue operationValue) {
        this.operation = operationValue;
        return this;
    }

    public SubscriptionReasonValue getReason() {
        return reason;
    }

    public SubscriptionDeactivateRequest setReason(SubscriptionReasonValue reason) {
        this.reason = reason;
        return this;
    }

    public SubscriptionPeriodValue getPeriod() {
        return period;
    }

    public SubscriptionDeactivateRequest setPeriod(SubscriptionPeriodValue period) {
        this.period = period;
        return this;
    }

    @Override
    public SubscriptionDeactivateRequest setSubscriptionId(String subscriptionId) {
        this.subscriptionId = subscriptionId;
        return this;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        final SubscriptionDeactivateRequest that = (SubscriptionDeactivateRequest) o;

        if (period != that.period) return false;
        if (reason != that.reason) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (reason != null ? reason.hashCode() : 0);
        result = 31 * result + (period != null ? period.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
                .append("operation", operation)
                .append("subscriptionId", subscriptionId)
                .append("reason", reason)
                .append("period", period)
                .toString();
    }
} public class SerializationException extends Exception {
    private static final long serialVersionUID = -3095196341869438153L;

    public SerializationException(String message) {
        super(message);
    }

    public SerializationException(Throwable cause) {
        super(cause);
    }

    public SerializationException(String message, Throwable cause) {
        super(message, cause);
    }
}
import com.amazon.dtasdk.base.InstantAccessOperationValue;
import com.amazon.dtasdk.base.InstantAccessResponse;
import com.amazon.dtasdk.base.SubscriptionResponse;
import com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseRequest;
import com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseResponse;
import com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseRequest;
import com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseResponse;
import com.amazon.dtasdk.v2.serialization.messages.SubscriptionActivateRequest;
import com.amazon.dtasdk.v2.serialization.messages.SubscriptionDeactivateRequest;
import com.amazon.dtasdk.serializer.SerializationException;
/*
 * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. 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.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazon.dtasdk.v2.servlets;


/**
 * <p>
 * This abstract servlet can be extended to implement the V2 Purchase/Subscription section of Instant Access API.
 * </p>
 *
 * <p>
 * When extending this servlet, you must implement the abstract methods relative to the four operations present in the
 * API. {@link #fulfillPurchase(FulfillPurchaseRequest)} is the method responsible for fulfilling a purchase, {@link
 * #revokePurchase(RevokePurchaseRequest)} is the method responsible for revoking a purchase, {@link
 * #processSubscriptionActivate(SubscriptionActivateRequest)} is the method responsible for activating a subscription and
 * {@link #processSubscriptionDeactivate(SubscriptionDeactivateRequest)} is the method responsible for deactivating a
 * subscription
 * </p>
 *
 * <p>
 * You must also implement the abstract method {@link #getCredentialStore()}. This method must provide a valid credential
 * store that will be used to verify the message authenticity.
 * </p>
 *
 */
public abstract class PurchaseServlet extends InstantAccessServlet {

    /**
     * Process the fulfill purchase request and return the response to whether or not the request succeeded.
     *
     * @param request
     *            the request relative to the fulfill purchase
     *
     * @return a FulfillPurchaseResponse object
     */
    public abstract FulfillPurchaseResponse fulfillPurchase(FulfillPurchaseRequest request);

    /**
     * Process the revoke purchase request and return the response to whether or not the request succeeded.
     *
     * @param request
     *            the request relative to the revoke purchase
     *
     * @return a RevokePurchaseResponse object
     */
    public abstract RevokePurchaseResponse revokePurchase(RevokePurchaseRequest request);

    /**
     * Process a subscription activation based on the request and returns the response to whether or not the request
     * succeeded.
     *
     * @param request
     *            the request object with information about the subscription
     *
     * @return a SubscriptionResponse object
     */
    public abstract SubscriptionResponse processSubscriptionActivate(SubscriptionActivateRequest request);

    /**
     * Process a subscription deactivation based on the request and returns the response to whether or not the request
     * succeeded.
     *
     * @param request
     *            the request object with information about the subscription
     *
     * @return a SubscriptionResponse object
     */
    public abstract SubscriptionResponse processSubscriptionDeactivate(SubscriptionDeactivateRequest request);