/***********************************************************
Copyright (C) 2018 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
 ***********************************************************/
package com.verisign.epp.codec.registry.v02;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.codec.gen.EPPCodecTst;
import com.verisign.epp.codec.gen.EPPEncodeDecodeStats;
import com.verisign.epp.codec.gen.EPPFactory;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.gen.EPPTransId;
import com.verisign.epp.codec.registry.v02.EPPRegistryDomain.HostModelSupported;
import com.verisign.epp.codec.registry.v02.EPPRegistryServices.EPPRegistryObjURI;
import com.verisign.epp.codec.registry.v02.EPPRegistryServicesExt.EPPRegistryExtURI;
import com.verisign.epp.codec.registry.v02.EPPRegistrySupportedStatus.Status;
import com.verisign.epp.codec.registry.v02.EPPRegistryZoneName.Form;
import com.verisign.epp.util.TestThread;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.fail;

public class EPPRegistryTst {
  /**
   * Number of unit test iterations to run. This is set in
   * <code>EPPCodecTst.main</code>
   */
  static private long numIterations = 1;

  /**
   * Test the registry info command and response for the zone list.
   */
  @Test
  public void testRegistryInfoZoneList() {
    EPPCodecTst.printStart("testRegistryInfoZoneList");

    // Zone List Info Command
    EPPRegistryInfoCmd theCommand = new EPPRegistryInfoCmd("ABC-12349", EPPRegistryInfoCmd.Scope.accessible);

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPRegistryZoneList zoneList = new EPPRegistryZoneList();
    EPPTransId respTransId = new EPPTransId("ABC-12345", "54322-XYZ");
    EPPRegistryInfoResp theResponse = new EPPRegistryInfoResp(respTransId, zoneList);
    zoneList.addZone(new EPPRegistryZoneSummary("EXAMPLE1", true, new GregorianCalendar(2012, 10, 1).getTime(),
          new GregorianCalendar(2012, 10, 15).getTime()));
    zoneList.addZone(new EPPRegistryZoneSummary("EXAMPLE2", false, new GregorianCalendar(2012, 9, 1).getTime(),
          new GregorianCalendar(2012, 9, 19).getTime()));

    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    theCommand = new EPPRegistryInfoCmd("ABC-12349", "EXAMPLE");

    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    // Test with contact policy information
    respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");
    EPPRegistryZone zoneInfo = createZone();

    theResponse = new EPPRegistryInfoResp(respTransId, new EPPRegistryZoneData(zoneInfo, true));
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    // Test without contact policy information
    zoneInfo.setContact(null);
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryInfoZoneList");
  }

  /**
   * Test the registry info command and response for the zone info.
   */
  @Test
  public void testRegistryInfoZoneInfo() {
    EPPCodecTst.printStart("testRegistryInfoZoneInfo");

    EPPTransId theTransId = new EPPTransId("ABC-12345", "54321-XYZ");

    // Test with contact policy, DNSSEC DS Data Interface, Host Object Model
    EPPRegistryZone zoneInfo = createZone(true, true, true);
    EPPRegistryInfoResp theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, true));
    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    // Test with contact policy, DNSSEC Key Data Interface, Host Object Model
    zoneInfo = createZone(true, false, true);
    theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, false));
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    // Test without contact policy, DNSSECDS Data Interface, Host Object Model
    zoneInfo = createZone(false, true, true);
    theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, true));
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    // Test without contact policy, DNSSEC Key Data Interface, Host Object
    // Model
    zoneInfo = createZone(false, false, true);
    theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, false));
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    // Test with contact policy, DNSSEC DS Data Interface, Host Attribute
    // Model
    zoneInfo = createZone(true, true, false);
    theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, true));
    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryInfoZoneInfo");
  }

  /**
   * Test the registry info command and response for the system info.
   */
  @Test
  public void testRegistryInfoSystemInfo() {
    EPPCodecTst.printStart("testRegistryInfoSystemInfo");

    EPPRegistryInfoCmd theCommand = new EPPRegistryInfoCmd("ABC-12345", EPPRegistryInfoCmd.Mode.system);

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPTransId theTransId = new EPPTransId("ABC-12345", "54322-XYZ");
    EPPRegistrySystemInfo theSystemInfo = new EPPRegistrySystemInfo(Integer.valueOf(200), Integer.valueOf(600000),
          Integer.valueOf(86400000), Integer.valueOf(10000), Integer.valueOf(10), Integer.valueOf(1000));
    EPPRegistryInfoResp theResponse = new EPPRegistryInfoResp(theTransId, theSystemInfo);
    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryInfoSystemInfo");
  }

  @Test
  public void testRegistryCheck() {
    EPPCodecTst.printStart("testRegistryCheck");

    EPPRegistryCheckCmd theCommand = new EPPRegistryCheckCmd("ABC-12345", "com");

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    theCommand = new EPPRegistryCheckCmd("ABC-12345", "com");
    theCommand.addName("weirdname");

    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    // Encode EPPRegistryInfo Response
    EPPRegistryCheckResp theResponse;
    EPPEncodeDecodeStats responseStats;

    EPPTransId respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");
    EPPRegistryCheckResult result = new EPPRegistryCheckResult("com", Boolean.FALSE);
    result.setReason("Already taken");
    theResponse = new EPPRegistryCheckResp(respTransId, result);

    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");
    List results = new ArrayList();
    result = new EPPRegistryCheckResult("com", Boolean.FALSE);
    result.setReason("Already taken");
    results.add(result);
    results.add(new EPPRegistryCheckResult("availtld", Boolean.FALSE));

    theResponse = new EPPRegistryCheckResp(respTransId, results);

    responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryCheck");
  }

  @Test
  public void testRegistryCreate() {
    EPPCodecTst.printStart("testRegistryCreate");

    EPPRegistryZone zone = createZone();
    zone.setName("newtld");

    EPPRegistryCreateCmd theCommand = null;
    theCommand = new EPPRegistryCreateCmd("ABC-12349", zone);

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPTransId respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");

    EPPRegistryCreateResp theResponse = new EPPRegistryCreateResp(respTransId, zone.getName().getName());
    Calendar baseCal = Calendar.getInstance();
    Calendar endCal = (Calendar) baseCal.clone();
    theResponse.setCreateDate(baseCal.getTime());
    endCal = (Calendar) baseCal.clone();
    endCal.add(Calendar.MONTH, 9);
    endCal.add(Calendar.YEAR, 10);

    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryCreate");
  }

  @Test
  public void testRegistryUpdate() {
    EPPCodecTst.printStart("testRegistryUpdate");

    EPPRegistryZone zone = new EPPRegistryZone();
    zone.setName("newtld");

    EPPRegistryUpdateCmd theCommand = null;
    theCommand = new EPPRegistryUpdateCmd("ABC-12349", zone);

    zone.setDomain(this.buildInfoDomain());
    zone.setHost(this.buildInfoHost(true));
    zone.setContact(this.buildContact());

    EPPRegistryServices services = new EPPRegistryServices();
    services.addObjURI(new EPPRegistryObjURI(EPPRegistryMapFactory.NS, Boolean.TRUE));
    EPPRegistryServicesExt svcExt = new EPPRegistryServicesExt();
    services.setExtension(svcExt);
    svcExt.addExtURI(new EPPRegistryExtURI(EPPRegistryMapFactory.NS, Boolean.TRUE));
    zone.setServices(services);

    zone.setCreatedBy("crId");
    zone.setCreatedDate(new Date());

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPTransId respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");

    EPPResponse theResponse = new EPPResponse(respTransId);

    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryUpdate");
  }

  @Test
  public void testRegistryDelete() {
    EPPCodecTst.printStart("testRegistryDelete");

    EPPRegistryDeleteCmd theCommand = null;
    theCommand = new EPPRegistryDeleteCmd("ABC-12349", "newetld");

    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPTransId respTransId = new EPPTransId(theCommand.getTransId(), "54321-XYZ");

    EPPResponse theResponse = new EPPResponse(respTransId);

    EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(responseStats);

    EPPCodecTst.printEnd("testRegistryDelete");
  }

  /**
   * Creates a {@link EPPRegistryZone} test instance. This can be used to
   * bootstrap testing of the Registry Mapping or a Registry Mapping extension.
   * The response will include the contact policy information and the DS Data
   * interface information. The most likely options are used, which include
   * inclusion of contact policies (thick), support for the DNSSEC DS Data
   * Interface, and support for the host object model of RFC 5731.
   * 
   * @return {@link EPPRegistryZone} instance that is populated with an initial
   *         set of .COM zone information.
   */
  public static EPPRegistryZone createZone() {
    return createZone(true, true, true);
  }

  /**
   * Creates a {@link EPPRegistryZone} test instance. This can be used to
   * bootstrap testing of the Registry Mapping or a Registry Mapping extension.
   * 
   * @param aContactPolicy
   *           Include the contact policy? If {@code true} the contact policy
   *           information will be included in the response; otherwise there
   *           will be no contact policy information.
   * 
   * @param aDsDataInterface
   *           Is the DNSSEC DS data interface supported? If {@code true} the
   *           DS data interface is supported; otherwise the Key data interface
   *           is supported.
   * 
   * @param aHostObjModel
   *           Is the host object model used in RFC 5731? If {@code true} then
   *           the host object model is used; otherwise the host attribute
   *           model is used.
   * 
   * @return {@link EPPRegistryZone} instance that is populated with an initial
   *         set of .COM zone information.
   */
  public static EPPRegistryZone createZone(boolean aContactPolicy, boolean aDsDataInterface,
        boolean aHostObjModel) {

    EPPRegistryZone zoneInfo = new EPPRegistryZone("com");
    zoneInfo.setGroup("1");

    EPPRegistryServices services = new EPPRegistryServices();
    services.addObjURI(new EPPRegistryObjURI("http://www.verisign.com/epp/rgp-poll-1.0", Boolean.TRUE));
    services.addObjURI(new EPPRegistryObjURI("urn:ietf:params:xml:ns:host-1.0", Boolean.TRUE));
    services.addObjURI(new EPPRegistryObjURI("urn:ietf:params:xml:ns:contact-1.0", Boolean.TRUE));
    services.addObjURI(new EPPRegistryObjURI("urn:ietf:params:xml:ns:domain-1.0", Boolean.TRUE));
    services.addObjURI(new EPPRegistryObjURI("http://www.verisign.com/epp/lowbalance-poll-1.0", Boolean.FALSE));
    EPPRegistryServicesExt svcExt = new EPPRegistryServicesExt();
    services.setExtension(svcExt);
    svcExt.addExtURI(new EPPRegistryExtURI("http://www.verisign-grs.com/epp/namestoreExt-1.1", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("urn:ietf:params:xml:ns:rgp-1.0", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("http://www.verisign.com/epp/sync-1.0", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("http://www.verisign.com/epp/idnLang-1.0", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("http://www.verisign.com/epp/jobsContact-1.0", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("http://www.verisign.com/epp/premiumdomain-1.0", Boolean.TRUE));
    svcExt.addExtURI(new EPPRegistryExtURI("urn:ietf:params:xml:ns:secDNS-1.1", Boolean.FALSE));
    zoneInfo.setServices(services);

    zoneInfo.setCreatedBy("crId");
    zoneInfo.setCreatedDate(new Date());
    zoneInfo.setLastUpdatedBy("upId");
    zoneInfo.setLastUpdatedDate(new Date());
    zoneInfo.setUnsupportedData(EPPRegistryZone.UnsupportedData.fail);

    EPPRegistryBatchJob batchJob = new EPPRegistryBatchJob("localTzBatch",
          "Batch with multiple local time schedules (name and offset)");
    batchJob.addSchedule(new EPPRegistryBatchSchedule("04:00:00", "EST5EDT"));
    batchJob.addSchedule(new EPPRegistryBatchSchedule("07:00:00-05:00", null));
    zoneInfo.addBatchJob(batchJob);

    batchJob = new EPPRegistryBatchJob("multiBatchSchedule", "Batch with multiple UTC schedules");
    batchJob.addSchedule(new EPPRegistryBatchSchedule("12:00:00Z", null));
    batchJob.addSchedule(new EPPRegistryBatchSchedule("12:00:00Z", EPPRegistryBatchSchedule.DayOfWeek.SUNDAY, null));
    batchJob.addSchedule(new EPPRegistryBatchSchedule("17:00:00Z", 15, null));
    zoneInfo.addBatchJob(batchJob);

    zoneInfo.addSystemZone(new EPPRegistryZoneName("EXAMPLE"));
    zoneInfo.addSystemZone(new EPPRegistryZoneName("EXAMPLE2", Form.aLabel));

    zoneInfo.setDomain(buildInfoDomain(aDsDataInterface, aHostObjModel));

    zoneInfo.setHost(buildInfoHost(aHostObjModel));

    if (aContactPolicy) {
      zoneInfo.setContact(buildContact());
    }
    return zoneInfo;
  }

  /**
   * Creates a {@link EPPRegistrySystemInfo} test instance. This can be used to
   * bootstrap testing of the Registry Mapping or a Registry Mapping extension.
   * 
   * @return {@link EPPRegistrySystemInfo} instance that is populated system
   *         data.
   */
  public static EPPRegistrySystemInfo createSystemInfo() {
    return new EPPRegistrySystemInfo(Integer.valueOf(200), Integer.valueOf(600000), Integer.valueOf(86400000), Integer.valueOf(10000),
          Integer.valueOf(10), Integer.valueOf(1000));
  }

  /**
   * Builds a {@link EPPRegistryDomain} instance for use in Registry Mapping
   * tests or Registry Mapping extension tests.
   * 
   * @return {@link EPPRegistryDomain} instance populated with an initial set of
   *               domain policy information.
   */
  public static EPPRegistryDomain buildInfoDomain() {
    return buildInfoDomain(true, true);
  }

  /**
   * Builds a {@link EPPRegistryDomain} instance for use in Registry Mapping
   * tests or Registry Mapping extension tests.
   * 
   * @param aDsDataInterface
   *           Is the DNSSEC DS data interface supported? IF {@code true} the
   *           DS data interface is supported; otherwise the Key data interface
   *           is supported.
   * 
   * @param aHostObjModel
   *           Is the host object model used in RFC 5731? If {@code true} then
   *           the host object model is used; otherwise the host attribute
   *           model is used.
   * 
   * @return {@link EPPRegistryDomain} instance populated with an initial set of
   *               domain policy information.
   */
  public static EPPRegistryDomain buildInfoDomain(boolean aDsDataInterface, boolean aHostObjModel) {
    EPPRegistryDomain domain = new EPPRegistryDomain();

    List domainNames = new ArrayList();
    EPPRegistryDomainName domainName = new EPPRegistryDomainName();
    domainName.setLevel(Integer.valueOf(2));
    domainName.setMinLength(Integer.valueOf(5));
    domainName.setMaxLength(Integer.valueOf(50));
    domainName.setAlphaNumStart(Boolean.valueOf(true));
    domainName.setAlphaNumEnd(Boolean.valueOf(false));
    domainName.setALabelSupported(Boolean.valueOf(true));
    domainName.setNameRegex(new EPPRegistryRegex("^[a-zA-Z\\d][a-zA-Z\\d\\-]{4,49}$",
          "5 to 50 DNS characters starting with alphanumeric"));

    EPPRegistryReservedNames reservedNames = new EPPRegistryReservedNames();
    List rNames = new ArrayList();
    reservedNames.setReservedNames(rNames);
    rNames.add("reserved1");
    rNames.add("reserved2");
    // reservedNames.setReservedNameURI("http://example.com/reservedNames");

    domainName.setReservedNames(reservedNames);
    domainNames.add(domainName);

    try {
      domainName = (EPPRegistryDomainName) domainName.clone();
      domainName.setLevel(Integer.valueOf(3));
      domainName.getReservedNames().setReservedNames(new ArrayList());
      domainName.getReservedNames().setReservedNameURI("http://testrn.vrsn.com");
      domainNames.add(domainName);
    }
    catch (CloneNotSupportedException e) {
      fail("failed to clone domainName");
    }

    domain.setDomainNames(domainNames);

    EPPRegistryIDN idn = new EPPRegistryIDN();
    idn.setIdnVersion("1.1");
    idn.setIdnaVersion("2008");
    idn.setUnicodeVersion("6.0");
    idn.addLanguage(new EPPRegistryLanguage("CHI", "http://www.iana.org/domains/idn-tables/tables/com_zh_1.1.txt",
          EPPRegistryLanguage.VariantStrategy.restricted));
    idn.addLanguage(new EPPRegistryLanguage("LATN", "http://www.iana.org/domains/idn-tables/tables/eu_latn_1.0.html",
          EPPRegistryLanguage.VariantStrategy.blocked));
    idn.setCommingleAllowed(Boolean.TRUE);
    domain.setIdn(idn);

    domain.setPremiumSupport(Boolean.valueOf(true));
    domain.setContactsSupported(Boolean.valueOf(false));

    domain.addContact(new EPPRegistryDomainContact(EPPRegistryDomainContact.Type.admin, 1, 4));
    domain.addContact(new EPPRegistryDomainContact(EPPRegistryDomainContact.Type.billing, 2, 5));
    domain.addContact(new EPPRegistryDomainContact(EPPRegistryDomainContact.Type.tech, 3, 6));

    domain.setNameServerLimit(new EPPRegistryDomainNSLimit(1, 16));

    if (aHostObjModel) {
      domain.setChildHostLimit(new EPPRegistryDomainHostLimit(0, null));
    }

    domain.addPeriod(new EPPRegistryDomainPeriod("create", Boolean.TRUE));
    domain.addPeriod(new EPPRegistryDomainPeriod("renew", 1, EPPRegistryPeriodType.Unit.y, 60,
          EPPRegistryPeriodType.Unit.m, 5, EPPRegistryPeriodType.Unit.y));
    domain.addPeriod(new EPPRegistryDomainPeriod("transfer", 1, EPPRegistryPeriodType.Unit.y, 8,
          EPPRegistryPeriodType.Unit.y, 3, EPPRegistryPeriodType.Unit.y));

    domain.addExceedMaxExDate(new EPPRegistryExceedMaxExDate(EPPRegistryExceedMaxExDate.Policy.fail, "renew"));
    domain.addExceedMaxExDate(new EPPRegistryExceedMaxExDate(EPPRegistryExceedMaxExDate.Policy.clip, "transfer"));

    domain.setTransferHoldPeriod(new EPPRegistryTransferHoldPeriodType(5, EPPRegistryPeriodType.Unit.d));

    domain.addGracePeriod(new EPPRegistryGracePeriod("create", 1, EPPRegistryPeriodType.Unit.d));
    domain.addGracePeriod(new EPPRegistryGracePeriod("renew", 2, EPPRegistryPeriodType.Unit.h));
    domain.addGracePeriod(new EPPRegistryGracePeriod("transfer", 3, EPPRegistryPeriodType.Unit.m));

    EPPRegistryRGP rgp = new EPPRegistryRGP();
    rgp.setPendingDeletePeriod(new EPPRegistryPendingDeletePeriodType(1, EPPRegistryPeriodType.Unit.m));
    rgp.setRedemptionPeriod(new EPPRegistryRedemptionPeriodType(1, EPPRegistryPeriodType.Unit.m));
    rgp.setPendingRestorePeriod(new EPPRegistryPendingRestorePeriodType(1, EPPRegistryPeriodType.Unit.m));
    domain.setRgp(rgp);

    EPPRegistryDNSSEC dnssec = new EPPRegistryDNSSEC();

    // DS Data Interface?
    if (aDsDataInterface) {
      EPPRegistryDS ds = new EPPRegistryDS(0, 13);
      ds.addAlgorithm(3);
      ds.addDigestType(1);
      dnssec.setDs(ds);
    } // Key Data Interface
    else {
      EPPRegistryKey key = new EPPRegistryKey(0, 13);
      key.addFlags(257);
      key.addProtocol(3);
      key.addAlgorithm(3);
      dnssec.setKey(key);
    }

    dnssec.setMaxSigLife(new EPPRegistryMaxSig(true, 1, 2, 3));
    dnssec.setUrgent(Boolean.TRUE);

    domain.setDnssec(dnssec);
    domain.setMaxCheckDomain(Integer.valueOf(12));

    EPPRegistrySupportedStatus supportedStatus = new EPPRegistrySupportedStatus();
    supportedStatus.addStatus(Status.DOMAIN_CLIENTDELETEPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_SERVERDELETEPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_CLIENTHOLD);
    supportedStatus.addStatus(Status.DOMAIN_SERVERHOLD);
    supportedStatus.addStatus(Status.DOMAIN_CLIENTRENEWPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_SERVERRENEWPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_CLIENTTRANSFERPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_SERVERTRANSFERPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_CLIENTUPDATEPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_SERVERUPDATEPROHIBITED);
    supportedStatus.addStatus(Status.DOMAIN_INACTIVE);
    supportedStatus.addStatus(Status.DOMAIN_OK);
    supportedStatus.addStatus(Status.DOMAIN_PENDINGCREATE);
    supportedStatus.addStatus(Status.DOMAIN_PENDINGDELETE);
    supportedStatus.addStatus(Status.DOMAIN_PENDINGRENEW);
    supportedStatus.addStatus(Status.DOMAIN_PENDINGTRANSFER);
    supportedStatus.addStatus(Status.DOMAIN_PENDINGUPDATE);
    domain.setSupportedStatus(supportedStatus);

    domain.setAuthInfoRegex(new EPPRegistryRegex("^.*$", "exp"));
    domain.setNullAuthInfoSupported(Boolean.FALSE);
    if (aHostObjModel) {
      domain.setHostModelSupported(HostModelSupported.hostObj);
    }
    else {
      domain.setHostModelSupported(HostModelSupported.hostAttr);
    }

    return domain;
  }

  /**
   * Builds a {@link EPPRegistryHost} instance for use in Registry Mapping
   * tests or Registry Mapping extension tests.
   *
   * @param aHostObjModel
   *           Is the host object model used in RFC 5731? If {@code true} then
   *           the host object model is used; otherwise the host attribute
   *           model is used.
   *
   * @return {@link EPPRegistryHost} instance populated with an initial set of
   *               host policy information.
   */
  public static EPPRegistryHost buildInfoHost(boolean aHostObjModel) {
    EPPRegistryHost host = new EPPRegistryHost();

    if (aHostObjModel) {
      host.setInternal(
            new EPPRegistryInternalHost(5, 15, EPPRegistryInternalHost.SharePolicy.perZone, Boolean.FALSE));
      host.setExternal(
            new EPPRegistryExternalHost(2, 12, EPPRegistryExternalHost.SharePolicy.perZone, Boolean.FALSE));

      host.setMaxCheckHost(Integer.valueOf(15));

      EPPRegistrySupportedStatus supportedStatus = new EPPRegistrySupportedStatus();
      supportedStatus.addStatus(Status.HOST_CLIENTDELETEPROHIBITED);
      supportedStatus.addStatus(Status.HOST_SERVERDELETEPROHIBITED);
      supportedStatus.addStatus(Status.HOST_CLIENTUPDATEPROHIBITED);
      supportedStatus.addStatus(Status.HOST_SERVERUPDATEPROHIBITED);
      supportedStatus.addStatus(Status.HOST_LINKED);
      supportedStatus.addStatus(Status.HOST_OK);
      supportedStatus.addStatus(Status.HOST_PENDINGCREATE);
      supportedStatus.addStatus(Status.HOST_PENDINGDELETE);
      supportedStatus.addStatus(Status.HOST_PENDINGTRANSFER);
      supportedStatus.addStatus(Status.HOST_PENDINGUPDATE);
      host.setSupportedStatus(supportedStatus);
    } // Host Attribute Model
    else {
      host.setInternal(new EPPRegistryInternalHost(5, 15, null, Boolean.FALSE));
      host.setExternal(new EPPRegistryExternalHost(2, 12, null, Boolean.FALSE));
    }

    host.setNameRegex(new EPPRegistryRegex("^.*$"));
    host.addInvalidIP("http://www.example.com/invalidip-1.txt");
    host.addInvalidIP("http://www.example.com/invalidip-2.txt");

    return host;

  }

  /**
   * Builds a {@link EPPRegistryContact} instance for use in Registry Mapping
   * tests or Registry Mapping extension tests.
   *
   * @return {@link EPPRegistryContact} instance populated with an initial set
   *               of contact policy information.
   */
  public static EPPRegistryContact buildContact() {
    EPPRegistryContact contact = new EPPRegistryContact();

    contact.setIntPostalInfoTypeSupport(EPPRegistryContact.PostalInfoTypeSupport.locOrIntSupport);

    contact.setContactIdRegex(new EPPRegistryRegex("^.*$"));
    contact.setContactIdPrefix("EX");
    contact.setSharePolicy(EPPRegistryContact.SharePolicy.perZone);
    contact.setAuthInfoRegex(new EPPRegistryRegex("^.*$", "exp"));

    contact.setMaxCheckContact(Integer.valueOf(15));

    EPPRegistryPostal postalInfo = new EPPRegistryPostal();
    postalInfo.setLocCharRegex(new EPPRegistryRegex("^.*$"));
    postalInfo.setName(new EPPRegistryContactName(5, 15));
    postalInfo.setOrg(new EPPRegistryContactOrg(2, 12));
    postalInfo.setVoiceRequired(Boolean.TRUE);
    postalInfo.setVoiceExt(new EPPRegistryMinMaxLength(5, 15));
    postalInfo.setFaxExt(new EPPRegistryMinMaxLength(5, 15));
    List emailRegex = new ArrayList();
    postalInfo.setEmailRegex(new EPPRegistryRegex("^.+\\..+$"));

    EPPRegistryContactAddress address = new EPPRegistryContactAddress();
    address.setStreet(new EPPRegistryContactStreet(2, 12, 0, 3));
    address.setCity(new EPPRegistryContactCity(5, 15));
    address.setStateProvince(new EPPRegistryContactStateProvince(1, 11));
    address.setPostalCode(new EPPRegistryContactPostalCode(2, 12));

    postalInfo.setAddress(address);

    contact.setMaxCheckContact(Integer.valueOf(5));

    contact.setPostalInfo(postalInfo);

    contact.setClientDisclosureSupported(Boolean.TRUE);

    EPPRegistrySupportedStatus supportedStatus = new EPPRegistrySupportedStatus();
    supportedStatus.addStatus(Status.CONTACT_CLIENTDELETEPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_SERVERDELETEPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_CLIENTTRANSFERPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_SERVERTRANSFERPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_CLIENTUPDATEPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_SERVERUPDATEPROHIBITED);
    supportedStatus.addStatus(Status.CONTACT_LINKED);
    supportedStatus.addStatus(Status.CONTACT_OK);
    supportedStatus.addStatus(Status.CONTACT_PENDINGCREATE);
    supportedStatus.addStatus(Status.CONTACT_PENDINGDELETE);
    supportedStatus.addStatus(Status.CONTACT_PENDINGTRANSFER);
    supportedStatus.addStatus(Status.CONTACT_PENDINGUPDATE);
    contact.setSupportedStatus(supportedStatus);

    contact.setTransferHoldPeriod(new EPPRegistryTransferHoldPeriodType(5, EPPRegistryPeriodType.Unit.d));

    return contact;
  }

  /**
   * JUNIT <code>suite</code> static method, which returns the tests associated
   * with <code>EPPRegistryTst</code>.
   */
  @BeforeClass
  public static void beforeClass() {
    EPPCodecTst.initEnvironment();

    // iterations Property
    String numIterProp = System.getProperty("iterations");

    if (numIterProp != null) {
      numIterations = Integer.parseInt(numIterProp);
    }

    // Add the EPPRegistryMapFactory to the EPPCodec.
    try {
      EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.registry.v02.EPPRegistryMapFactory");
    }
    catch (EPPCodecException e) {
      Assert.fail("EPPCodecException adding EPPRegistryMapFactory to EPPCodec: " + e);
    }
  }

  /**
   * Sets the number of iterations to run per test.
   * 
   * @param aNumIterations
   *           number of iterations to run per test
   */
  public static void setNumIterations(long aNumIterations) {
    numIterations = aNumIterations;
  }
}
