net.authorize.api.controller.test.ApiCoreTestBase.java Source code

Java tutorial

Introduction

Here is the source code for net.authorize.api.controller.test.ApiCoreTestBase.java

Source

package net.authorize.api.controller.test;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.xml.datatype.DatatypeFactory;

import junit.framework.Assert;
import net.authorize.Environment;
import net.authorize.Merchant;
import net.authorize.UnitTestData;
import net.authorize.api.contract.v1.ANetApiRequest;
import net.authorize.api.contract.v1.ANetApiResponse;
import net.authorize.api.contract.v1.ARBSubscriptionType;
import net.authorize.api.contract.v1.ARBSubscriptionUnitEnum;
import net.authorize.api.contract.v1.BankAccountType;
import net.authorize.api.contract.v1.BankAccountTypeEnum;
import net.authorize.api.contract.v1.CreditCardTrackType;
import net.authorize.api.contract.v1.CreditCardType;
import net.authorize.api.contract.v1.CustomerAddressType;
import net.authorize.api.contract.v1.CustomerDataType;
import net.authorize.api.contract.v1.CustomerPaymentProfileType;
import net.authorize.api.contract.v1.CustomerProfileType;
import net.authorize.api.contract.v1.CustomerType;
import net.authorize.api.contract.v1.CustomerTypeEnum;
import net.authorize.api.contract.v1.DriversLicenseType;
import net.authorize.api.contract.v1.EcheckTypeEnum;
import net.authorize.api.contract.v1.EncryptedTrackDataType;
import net.authorize.api.contract.v1.KeyBlock;
import net.authorize.api.contract.v1.MerchantAuthenticationType;
import net.authorize.api.contract.v1.MessageTypeEnum;
import net.authorize.api.contract.v1.MessagesType;
import net.authorize.api.contract.v1.MessagesType.Message;
import net.authorize.api.contract.v1.NameAndAddressType;
import net.authorize.api.contract.v1.ObjectFactory;
import net.authorize.api.contract.v1.OrderType;
import net.authorize.api.contract.v1.PayPalType;
import net.authorize.api.contract.v1.PaymentScheduleType;
import net.authorize.api.contract.v1.PaymentType;
import net.authorize.api.controller.base.ApiOperationBase;
import net.authorize.api.controller.base.IApiOperation;
import net.authorize.data.xml.reporting.ReportingDetails;
import net.authorize.util.Constants;
import net.authorize.util.DateUtil;
import net.authorize.util.LogHelper;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

public abstract class ApiCoreTestBase {

    protected static Log logger = LogFactory.getLog(ApiCoreTestBase.class);

    protected static HashMap<String, String> errorMessages = null;

    //protected static Environment environment = Environment.HOSTED_VM;
    protected static Environment environment = Environment.SANDBOX;

    static Merchant merchant = null;
    static String apiLoginIdKey = null;
    static String transactionKey = null;
    static String md5HashKey = null;

    protected static String apiLoginIdKeyApplePay = null;
    protected static String transactionKeyApplePay = null;
    protected static String md5HashKeyApplePay = null;

    DatatypeFactory datatypeFactory = null;
    GregorianCalendar pastDate = null;
    GregorianCalendar nowDate = null;
    GregorianCalendar futureDate = null;
    String nowString = null;
    Date now = null;

    protected String refId = null;
    protected int counter = 0;
    protected String counterStr = null;

    protected MerchantAuthenticationType merchantAuthenticationType = null;

    protected ARBSubscriptionType arbSubscriptionOne = null;
    protected ARBSubscriptionType arbSubscriptionTwo = null;
    protected BankAccountType bankAccountOne = null;
    protected CreditCardTrackType trackDataOne = null;
    protected CreditCardType creditCardOne = null;
    protected CustomerAddressType customerAddressOne = null;
    protected CustomerDataType customerDataOne = null;
    protected CustomerPaymentProfileType customerPaymentProfileOne = null;
    protected CustomerProfileType customerProfileType = null;
    protected CustomerType customerOne = null;
    protected CustomerType customerTwo = null;
    protected DriversLicenseType driversLicenseOne = null;
    protected EncryptedTrackDataType encryptedTrackDataOne = null;
    protected NameAndAddressType nameAndAddressTypeOne = null;
    protected NameAndAddressType nameAndAddressTypeTwo = null;
    protected OrderType orderType = null;
    protected PaymentScheduleType paymentScheduleTypeOne = null;
    protected PaymentType paymentOne = null;
    protected PayPalType payPalOne = null;

    protected Mockery mockContext = null;
    protected static ObjectFactory factory = null;
    private Random random = new Random();

    static {
        //getPropertyFromNames get the value from properties file or environment
        apiLoginIdKey = UnitTestData.getPropertyFromNames(Constants.ENV_API_LOGINID, Constants.PROP_API_LOGINID);
        transactionKey = UnitTestData.getPropertyFromNames(Constants.ENV_TRANSACTION_KEY,
                Constants.PROP_TRANSACTION_KEY);
        md5HashKey = UnitTestData.getPropertyFromNames(Constants.ENV_MD5_HASHKEY, Constants.PROP_MD5_HASHKEY);

        apiLoginIdKeyApplePay = UnitTestData.getPropertyFromNames(Constants.ENV_API_LOGINID_APPLEPAY,
                Constants.PROP_API_LOGINID_APPLEPAY);
        transactionKeyApplePay = UnitTestData.getPropertyFromNames(Constants.ENV_TRANSACTION_KEY_APPLEPAY,
                Constants.PROP_TRANSACTION_KEY_APPLEPAY);
        md5HashKeyApplePay = UnitTestData.getPropertyFromNames(Constants.ENV_MD5_HASHKEY_APPLEPAY,
                Constants.PROP_MD5_HASHKEY_APPLEPAY);

        //require only one cnp or cp merchant keys
        if ((null != apiLoginIdKey && null != transactionKey)) {
            logger.debug("Merchant keys are present.");
        } else {
            throw new IllegalArgumentException(
                    "LoginId and/or TransactionKey have not been set. " + "Merchant keys are required.");
        }

        if ((null != apiLoginIdKeyApplePay && null != transactionKeyApplePay)) {
            logger.debug("Merchant ApplePay keys are present.");
        } else {
            // If one is null. make all equal to the regular key values.
            apiLoginIdKeyApplePay = apiLoginIdKey;
            transactionKeyApplePay = transactionKey;
            md5HashKeyApplePay = md5HashKey;
        }

        if (null != apiLoginIdKey && null != transactionKey) {
            merchant = Merchant.createMerchant(environment, apiLoginIdKey, transactionKey);
        }
        if (null == merchant) {
            Assert.fail("Merchant login is not set");
        }

        errorMessages = new HashMap<String, String>();
        factory = new ObjectFactory();
    }

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        errorMessages.put("E00003", "");
        errorMessages.put("E00027", "");
        errorMessages.put("E00040", "");
        errorMessages.put("E00090", "PaymentProfile cannot be sent with payment data.");
        errorMessages.put("E00091", "PaymentProfileId cannot be sent with payment data.");
        errorMessages.put("E00092", "ShippingProfileId cannot be sent with ShipTo data.");
        errorMessages.put("E00093", "PaymentProfile cannot be sent with billing data.");
        errorMessages.put("E00095", "ShippingProfileId is not provided within Customer Profile.");
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public void setUp() throws Exception {

        mockContext = new Mockery();

        //initialize counter
        counter = random.nextInt((int) Math.pow(2, 24));
        counterStr = getRandomString("");

        now = Calendar.getInstance().getTime();
        nowString = DateUtil.getFormattedDate(now, ReportingDetails.DATE_FORMAT);

        datatypeFactory = DatatypeFactory.newInstance();
        //TODO add / subtract relative
        pastDate = new GregorianCalendar(2010, 01, 01);
        nowDate = new GregorianCalendar();
        futureDate = new GregorianCalendar(2020, 12, 31);

        merchantAuthenticationType = new MerchantAuthenticationType();
        merchantAuthenticationType.setName(apiLoginIdKey);
        merchantAuthenticationType.setTransactionKey(transactionKey);

        //      merchantAuthenticationType.setSessionToken(getRandomString("SessionToken"));
        //      merchantAuthenticationType.setPassword(getRandomString("Password"));
        //       merchantAuthenticationType.setMobileDeviceId(getRandomString("MobileDevice"));

        //       ImpersonationAuthenticationType impersonationAuthenticationType = new ImpersonationAuthenticationType();
        //       impersonationAuthenticationType.setPartnerLoginId(CnpApiLoginIdKey);
        //       impersonationAuthenticationType.setPartnerTransactionKey(CnpTransactionKey);
        //       merchantAuthenticationType.setImpersonationAuthentication(impersonationAuthenticationType);

        customerProfileType = new CustomerProfileType();
        customerProfileType.setMerchantCustomerId(getRandomString("Customer"));
        customerProfileType.setDescription(getRandomString("CustomerDescription"));
        customerProfileType.setEmail(counterStr + ".customerProfileType@test.anet.net");

        //make sure these elements are initialized by calling get as it uses lazy initialization
        //List<CustomerPaymentProfileType> paymentProfiles = 
        customerProfileType.getPaymentProfiles();
        //List<CustomerAddressType> addresses = 
        customerProfileType.getShipToList();

        //XXX HIDE CreditCardType 
        creditCardOne = new CreditCardType();
        creditCardOne.setCardNumber("4111111111111111");
        creditCardOne.setExpirationDate("2038-12");
        //      creditCardOne.setCardCode("");

        //XXX HIDE BankAccountType 
        bankAccountOne = new BankAccountType();
        bankAccountOne.setAccountType(BankAccountTypeEnum.SAVINGS);
        bankAccountOne.setRoutingNumber("125000000");
        bankAccountOne.setAccountNumber(getRandomString("A/C#"));
        bankAccountOne.setNameOnAccount((getRandomString("A/CName")));
        bankAccountOne.setEcheckType(EcheckTypeEnum.WEB);
        bankAccountOne.setBankName(getRandomString("Bank"));
        bankAccountOne.setCheckNumber(counterStr);

        //XXX HIDE CreditCardTrackType 
        trackDataOne = new CreditCardTrackType();
        trackDataOne.setTrack1(getRandomString("Track1"));
        trackDataOne.setTrack2(getRandomString("Track2"));

        //XXX HIDE EncryptedTrackDataType 
        encryptedTrackDataOne = new EncryptedTrackDataType();
        KeyBlock keyBlock = new KeyBlock();
        //keyBlock.setValue(value);
        encryptedTrackDataOne.setFormOfPayment(keyBlock);

        payPalOne = new PayPalType();
        payPalOne.setSuccessUrl(getRandomString("https://success.anet.net"));
        payPalOne.setCancelUrl(getRandomString("https://cancel.anet.net"));
        payPalOne.setPaypalLc(getRandomString("Lc"));
        payPalOne.setPaypalHdrImg(getRandomString("Hdr"));
        payPalOne.setPaypalPayflowcolor(getRandomString("flowClr"));
        payPalOne.setPayerID(getRandomString("PayerId"));

        paymentOne = new PaymentType();
        paymentOne.setCreditCard(creditCardOne);
        //paymentOne.setBankAccount(bankAccountOne);
        //paymentOne.setTrackData(trackDataOne);
        //paymentOne.setEncryptedTrackData(encryptedTrackDataOne);
        //paymentOne.setPayPal( payPalOne);

        //      driversLicenseOne = new DriversLicenseType();
        //      driversLicenseOne.setNumber(getRandomString("DLNumber"));
        //      driversLicenseOne.setState(getRandomString("WA"));
        //      driversLicenseOne.setDateOfBirth(nowString);

        customerAddressOne = new CustomerAddressType();
        customerAddressOne.setFirstName(getRandomString("FName"));
        customerAddressOne.setLastName(getRandomString("LName"));
        customerAddressOne.setCompany(getRandomString("Company"));
        customerAddressOne.setAddress(getRandomString("StreetAdd"));
        customerAddressOne.setCity("Bellevue");
        customerAddressOne.setState("WA");
        customerAddressOne.setZip("98000");
        customerAddressOne.setCountry("USA");
        customerAddressOne.setPhoneNumber(formatToPhone(counter));
        customerAddressOne.setFaxNumber(formatToPhone(counter + 1));
        customerPaymentProfileOne = new CustomerPaymentProfileType();
        customerPaymentProfileOne.setCustomerType(CustomerTypeEnum.INDIVIDUAL);
        customerPaymentProfileOne.setPayment(paymentOne);
        //       customerPaymentProfileOne.setBillTo(customerAddressOne);
        //       customerPaymentProfileOne.setDriversLicense(driversLicenseOne);
        //       customerPaymentProfileOne.setTaxId(getRandomString("XX"));

        customerOne = new CustomerType();
        customerOne.setType(CustomerTypeEnum.INDIVIDUAL);
        customerOne.setId(getRandomString("Id"));
        customerOne.setEmail(counterStr + ".customerOne@test.anet.net");
        customerOne.setPhoneNumber(formatToPhone(counter));
        customerOne.setFaxNumber(formatToPhone(counter + 1));
        customerOne.setDriversLicense(driversLicenseOne);
        customerOne.setTaxId("911011011");//"123-45-6789");//TODO

        customerTwo = new CustomerType();

        PaymentScheduleType.Interval interval = new PaymentScheduleType.Interval();
        interval.setLength((short) 1);
        interval.setUnit(ARBSubscriptionUnitEnum.MONTHS);

        orderType = new OrderType();
        //TODO ADD VALIDATION ON INVOICE LENGTH
        orderType.setInvoiceNumber(getRandomString("Inv:"));
        orderType.setDescription(getRandomString("Description"));

        nameAndAddressTypeOne = new NameAndAddressType();
        nameAndAddressTypeOne.setFirstName(getRandomString("FName"));
        nameAndAddressTypeOne.setLastName(getRandomString("LName"));
        nameAndAddressTypeOne.setCompany(getRandomString("Company"));
        nameAndAddressTypeOne.setAddress(getRandomString("Address"));
        nameAndAddressTypeOne.setCity(getRandomString("City"));
        nameAndAddressTypeOne.setState(getRandomString("State"));
        nameAndAddressTypeOne.setZip("98004");
        nameAndAddressTypeOne.setCountry("USA");

        nameAndAddressTypeTwo = new NameAndAddressType();
        nameAndAddressTypeTwo.setFirstName(getRandomString("FName"));
        nameAndAddressTypeTwo.setLastName(getRandomString("LName"));
        nameAndAddressTypeTwo.setCompany(getRandomString("Company"));
        nameAndAddressTypeTwo.setAddress(getRandomString("Address"));
        nameAndAddressTypeTwo.setCity(getRandomString("City"));
        nameAndAddressTypeTwo.setState(getRandomString("State"));
        nameAndAddressTypeTwo.setZip("98004");
        nameAndAddressTypeTwo.setCountry("USA");

        paymentScheduleTypeOne = new PaymentScheduleType();
        paymentScheduleTypeOne.setInterval(interval);
        paymentScheduleTypeOne.setStartDate(datatypeFactory.newXMLGregorianCalendar(nowDate));
        paymentScheduleTypeOne.setTotalOccurrences((short) 5);
        paymentScheduleTypeOne.setTrialOccurrences((short) 0);

        arbSubscriptionOne = new ARBSubscriptionType();
        arbSubscriptionOne.setAmount(setValidSubscriptionAmount(counter));
        arbSubscriptionOne.setBillTo(nameAndAddressTypeOne);
        arbSubscriptionOne.setCustomer(customerOne);
        arbSubscriptionOne.setName(getRandomString("Name"));
        arbSubscriptionOne.setOrder(orderType);
        arbSubscriptionOne.setPayment(paymentOne);
        arbSubscriptionOne.setPaymentSchedule(paymentScheduleTypeOne);
        arbSubscriptionOne.setShipTo(nameAndAddressTypeOne);
        arbSubscriptionOne.setTrialAmount(setValidSubscriptionAmount(0));

        customerDataOne = new CustomerDataType();
        customerDataOne.setDriversLicense(customerOne.getDriversLicense());
        customerDataOne.setEmail(customerOne.getEmail());
        customerDataOne.setId(customerOne.getId());
        customerDataOne.setTaxId(customerOne.getTaxId());
        customerDataOne.setType(customerOne.getType());

        refId = counterStr;
    }

    @After
    public void tearDown() throws Exception {
    }

    protected String getRandomString(String title) {
        return String.format("%s%d", title, counter);

    }

    public String formatToPhone(int number) {
        DecimalFormat formatter = new DecimalFormat("0000000000");
        String formattedNumber = formatter.format(number).toString();
        return formattedNumber.substring(0, 3) + "-" + formattedNumber.substring(3, 6) + "-"
                + formattedNumber.substring(6, 10);
    }

    public BigDecimal setValidTaxAmount(BigDecimal amount) {
        return new BigDecimal(amount.doubleValue() * TAX_RATE);
    }

    public BigDecimal setValidTransactionAmount(int number) {
        return setValidAmount(number, MAX_TRANSACTION_AMOUNT);
    }

    public BigDecimal setValidSubscriptionAmount(int number) {
        return setValidAmount(number, MAX_SUBSCRIPTION_AMOUNT);
    }

    private BigDecimal setValidAmount(int number, int maxAmount) {
        return new BigDecimal(number > maxAmount ? (number % maxAmount) : number);
    }

    static ANetApiResponse errorResponse = null;

    protected ANetApiResponse getErrorResponse() {
        return errorResponse;
    }

    private int MAX_SUBSCRIPTION_AMOUNT = 1000;//214747;
    private int MAX_TRANSACTION_AMOUNT = 10000;//214747;
    private double TAX_RATE = 0.10d;

    protected static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> S executeTestRequestWithSuccess(
            Q request, Class<T> controllerClass, Environment execEnvironment) {
        S response = executeTestRequest(true, request, controllerClass, execEnvironment);

        return response;
    }

    protected static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> S executeTestRequestWithFailure(
            Q request, Class<T> controllerClass, Environment execEnvironment) {
        S response = executeTestRequest(false, request, controllerClass, execEnvironment);

        return response;
    }

    @SuppressWarnings("unchecked")
    private static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> S executeTestRequest(
            boolean successExpected, Q request, Class<T> controllerClass, Environment execEnvironment) {
        LogHelper.debug(logger, "Created %s Request: '%s'", request.getClass(), request);

        S response = null;
        T controller = null;
        errorResponse = null;
        try {
            Class<?>[] parameterTypes = new Class<?>[] { request.getClass() };
            Constructor<T> constructor = controllerClass.getConstructor(parameterTypes);
            Object controllerObject = constructor.newInstance(request);
            controller = (T) controllerObject;
            ANetApiResponse baseResponse = controller.executeWithApiResponse(execEnvironment);
            LogHelper.info(logger, "%s ResultCode: %s", controllerClass, controller.getResultCode());
            LogHelper.info(logger, "%s Results:    %s", controllerClass, controller.getResults());
            response = (S) baseResponse;

        } catch (Exception e) {
            LogHelper.error(logger, "Exception : '%s' during %s", e.getMessage(), controllerClass);
        }
        if (successExpected) {
            processFailureResult(true, controller, response);
            validateSuccess(controller, response);
        } else {
            validateFailure(controller, response);
        }
        if (null == response && null != controller && null != controller.getErrorResponse()) {
            errorResponse = controller.getErrorResponse();
        }

        return response;
    }

    protected static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> void processFailureResult(
            boolean fail, T controller, S response) {
        //in case there are errors, log the error messages
        if (MessageTypeEnum.OK != controller.getResultCode()) {
            for (String aMessage : controller.getResults()) {
                LogHelper.info(logger, "Controller Messages: '%s' ", aMessage);
            }
            displayResponse(response, "Failure Messsages");
            ANetApiResponse errorResponse = controller.getErrorResponse();
            displayResponse(errorResponse, "Error Response Messages");
            if (fail) {
                Assert.fail("Request failed.");
            }
        }
    }

    protected static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> void validateSuccess(
            T controller, S response) {
        Assert.assertEquals(MessageTypeEnum.OK, controller.getResultCode());
        Assert.assertNull(controller.getErrorResponse());
        Assert.assertNotNull(response);
        displayResponse(response, "Success Messages");
    }

    protected static <Q extends ANetApiRequest, S extends ANetApiResponse, T extends ApiOperationBase<Q, S>> void validateFailure(
            T controller, S response) {
        Assert.assertEquals(MessageTypeEnum.ERROR, controller.getResultCode());
        //TODO Until error response is fixed
        //Assert.assertNotNull(controller.getErrorResponse());
        //Assert.assertNull(response);
        processFailureResult(false, controller, response);
    }

    private static void displayResponse(ANetApiResponse response, String source) {
        LogHelper.info(logger, "Source '%s' ", source);
        if (null != response) {
            MessagesType messageType = response.getMessages();
            if (null != messageType) {
                LogHelper.info(logger, "MessageCode: '%s' ", messageType.getResultCode().toString());
                for (Message aMessage : messageType.getMessage()) {
                    LogHelper.info(logger, "Message: '%s':'%s' ", aMessage.getCode(), aMessage.getText());
                }
            }
        }
    }

    protected void validateErrorCode(MessagesType messagesType, String errorCode) {
        MessagesType.Message firstError = getFirstErrorMessage(messagesType);
        if (null != firstError) {
            Assert.assertEquals(errorCode, firstError.getCode());
            if (errorMessages.containsKey(errorCode)) {
                String message = errorMessages.get(errorCode);
                if (!message.isEmpty()) {
                    Assert.assertEquals(message, firstError.getText());
                }
            }
        }
    }

    protected static String getFirstErrorCode(MessagesType messagesType) {
        MessagesType.Message errorMessage = getFirstErrorMessage(messagesType);
        return ((null != errorMessage) ? errorMessage.getCode() : null);
    }

    protected static String getFirstErrorText(MessagesType messagesType) {
        MessagesType.Message errorMessage = getFirstErrorMessage(messagesType);
        return ((null != errorMessage) ? errorMessage.getText() : null);
    }

    protected static MessagesType.Message getFirstErrorMessage(MessagesType messagesType) {
        MessagesType.Message errorMessage = null;
        if (null != messagesType.getMessage()) {
            for (MessagesType.Message aMessage : messagesType.getMessage()) {
                errorMessage = aMessage;
                break;
            }

        }

        return errorMessage;

    }

    protected <Q extends ANetApiRequest, S extends ANetApiResponse> void setMockControllerExpectations(
            final IApiOperation<Q, S> mockController, final Q mockRequest, final S mockResponse,
            final ANetApiResponse errorResponse, final List<String> results, final MessageTypeEnum messageType) {

        final net.authorize.Environment mockEnvironment = net.authorize.Environment.CUSTOM;
        mockContext.checking(new Expectations() {
            {
                oneOf(mockController).execute();
                oneOf(mockController).execute(mockEnvironment);
                oneOf(mockController).getApiResponse();
                will(returnValue(mockResponse));
                oneOf(mockController).executeWithApiResponse();
                will(returnValue(mockResponse));
                oneOf(mockController).executeWithApiResponse(mockEnvironment);
                will(returnValue(mockResponse));
                oneOf(mockController).getResults();
                will(returnValue(results));
                oneOf(mockController).getResultCode();
                will(returnValue(messageType));
                oneOf(mockController).getErrorResponse();
                will(returnValue(errorResponse));
            }
        });

        if (null != mockRequest && null != mockResponse) {
            mockResponse.setRefId(mockRequest.getRefId());
        }
        logger.info(String.format("Request: %s", mockRequest));
        showProperties(mockRequest);
        logger.info(String.format("Response: %s", mockResponse));
        showProperties(mockResponse);
    }

    @SuppressWarnings("unchecked")
    protected <Q extends ANetApiRequest, S extends ANetApiResponse> IApiOperation<Q, S> getMockController() {
        return mockContext.mock(IApiOperation.class);
    }

    public static void showProperties(Object bean) {
        if (null == bean) {
            return;
        }
        try {
            BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class);
            PropertyDescriptor[] props = info.getPropertyDescriptors();
            for (PropertyDescriptor pd : props) {
                String name = pd.getName();
                Method getter = pd.getReadMethod();
                Class<?> type = pd.getPropertyType();

                if (null != getter && !"class".equals(name)) {
                    Object value = getter.invoke(bean);
                    logger.info(String.format("Type: '%s', Name:'%s', Value:'%s'", type, name, value));
                    processCollections(type, name, value);
                    //process compositions of custom classes
                    if (null != value && 0 <= type.toString().indexOf("net.authorize.")) {
                        showProperties(value);
                    }
                }
            }
        } catch (Exception e) {
            logger.error(String.format("Exception during navigating properties: Message: %s, StackTrace: %s",
                    e.getMessage(), e.getStackTrace()));
        }
    }

    public static void processCollections(Class<?> type, String name, Object value) {
        if (null != type) {
            if (Collection.class.isAssignableFrom(type)) {
                logger.info(String.format("Iterating on Collection: '%s'", name));
                for (Object aValue : (Collection<?>) value) {
                    showProperties(aValue);
                }
            }
            if (Map.class.isAssignableFrom(type)) {
                logger.info(String.format("Iterating on Map: '%s'", name));
                for (Object aValue : ((Map<?, ?>) value).values()) {
                    showProperties(aValue);
                }
            }
        }
    }
}