/***********************************************************
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
 ***********************************************************/
package com.verisign.epp.codec.launchpolicy.v01;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.verisign.epp.codec.gen.EPPCodecComponent;
import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.codec.gen.EPPDecodeException;
import com.verisign.epp.codec.gen.EPPEncodeException;
import com.verisign.epp.codec.gen.EPPUtil;
import com.verisign.epp.util.EqualityUtil;

/**
 * {@code EPPLaunchPolicyPhase} represents the policies for a zone phase.
 */
public class EPPLaunchPolicyPhase implements EPPCodecComponent {

  /**
   * {@code Phase} defines the type of phase, which include the following
   * possible values:<br>
   * <ul>
   * <li>{@code preDelegation} - Phase when pre-delegation testing is done.
   * </li>
   * <li>{@code preLaunch} - Phase prior to the sunrise phase where no writable
   * operations will be allowed.</li>
   * <li>{@code sunrise} - Phase when trademark holders can submit registration
   * applications with trademark information that can be validated by the
   * server.</li>
   * <li>{@code landrush} - Post-sunrise phase when non-trademark holders are
   * allowed to register domain names.</li>
   * <li>{@code claims} - Trademark claims phase as defined by Trademark
   * Clearinghouse model of displaying a claims notice to clients for domain
   * names that match trademarks.</li>
   * <li>{@code open} - Post-launch phase that is also referred to as "steady
   * state". Servers MAY require additional trademark protection with this
   * phase.</li>
   * <li>{@code custom} - Custom launch phase that is defined using the "name"
   * attribute.</li>
   * </ul>
   */
  public static enum Phase {
    preDelegation("pre-delegation"), preLaunch("pre-launch"), sunrise("sunrise"), landrush("landrush"), claims(
          "claims"), open("open"), custom("custom");

    private final String phaseStr;

    /**
     * Define the string value for the enumerated value.
     *
     * @param aPhaseStr
     *           Enumerated value string
     */
    Phase(String aPhaseStr) {
      this.phaseStr = aPhaseStr;
    }

    /**
     * Get the phase enumerated value given the matching string.
     *
     * @param aString
     *           {@code Phase} enumerated string to convert to an enumerated
     *           {@code Phase} instance.
     *
     * @return Enumerated {@code Phase} value matching the {@code String}.
     *
     * @throws InvalidParameterException
     *            If {@code aString} does not match an enumerated
     *            {@code Phase} string value.
     */
    public static Phase getPhase(String aString) {
      if (aString.equals(preDelegation.phaseStr)) {
        return preDelegation;
      }
      else if (aString.equals(preLaunch.phaseStr)) {
        return preLaunch;
      }
      else if (aString.equals(sunrise.phaseStr)) {
        return sunrise;
      }
      else if (aString.equals(landrush.phaseStr)) {
        return landrush;
      }
      else if (aString.equals(claims.phaseStr)) {
        return claims;
      }
      else if (aString.equals(open.phaseStr)) {
        return open;
      }
      else if (aString.equals(custom.phaseStr)) {
        return custom;
      }
      else {
        throw new InvalidParameterException("Phase enum value of " + aString + " is not valid.");
      }
    }

    /**
     * Convert the enumerated {@code Phase} value to a {@code String}.
     */
    @Override
    public String toString() {
      return this.phaseStr;
    }

  }

  /**
   * {@code Mode} defines how the phase operates, which include the following
   * possible values:<br>
   * <ul>
   * <li>{@code fcfs} - In this mode, each domain name is immediately created
   * and there is no use of an application identifier.</li>
   * <li>{@code pendingRegistration} - In this mode, the domain name is created
   * with the "pendingCreate" status with no use of an application identifier.
   * </li>
   * <li>{@code pendingApplication} - In this mode, the domain name, referred
   * to as a domain application, is created in the "pendingCreate" status with
   * the server returning an application identifier in the create response for
   * the client to use in subsequent commands (info, update, delete). When a
   * domain application is allocated, it will become a domain without the use
   * of an application identifier.</li>
   * </ul>
   */
  public static enum Mode {
    fcfs("fcfs"), pendingRegistration("pending-registration"), pendingApplication("pending-application");

    private final String modeStr;

    /**
     * Define the string value for the enumerated value.
     *
     * @param aModeStr
     *           Enumerated value string
     */
    Mode(String aModeStr) {
      this.modeStr = aModeStr;
    }

    /**
     * Get the mode enumerated value given the matching string.
     *
     * @param aString
     *           {@code Mode} enumerated string to convert to an enumerated
     *           {@code Mode} instance.
     *
     * @return Enumerated {@code Mode} value matching the {@code String}.
     *
     * @throws InvalidParameterException
     *            If {@code aString} does not match an enumerated {@code Mode}
     *            string value.
     */
    public static Mode getMode(String aString) {
      if (aString.equals(fcfs.modeStr)) {
        return fcfs;
      }
      else if (aString.equals(pendingRegistration.modeStr)) {
        return pendingRegistration;
      }
      else if (aString.equals(pendingApplication.modeStr)) {
        return pendingApplication;
      }
      else {
        throw new InvalidParameterException("Mode enum value of " + aString + " is not valid.");
      }
    }

    /**
     * Convert the enumerated {@code Mode} value to a {@code String}.
     */
    @Override
    public String toString() {
      return this.modeStr;
    }

  }

  /**
   * Possible mark validation models supported by the phase.
   */
  public static enum MarkValidation implements java.io.Serializable,Cloneable {
    /**
     * Indicates support for the "code" Mark Validation Model, where the mark
     * code by itself is used to validate that the mark matches the domain
     * name. This model is supported using the &lt;launch:codeMark&gt; element
     * with just the &lt;launch:code&gt; element.
     */
    code,

    /**
     * Indicates support for the "mark" Mark Validation Model, where the mark
     * information is passed without any other validation element. The server
     * will use some custom form of validation to validate that the mark
     * information is authentic. This model is supported using the
     * &lt;launch:codeMark&gt; element with just the &lt;mark:mark&gt;
     * element.
     */
    mark,
    /**
     * Indicates support for the "code with mark" Mark Validation Model, where
     * the code is used along with the mark information by the server to
     * validate the mark utilizing an external party. This model is supported
     * using the &lt;launch:codeMark&gt; element that contains both the
     * &lt;launch:code&gt; and the &lt;mark:mark&gt; elements.
     */
    codeWithMark,
    /**
     * Indicates support for the "signed mark" Mark Validation Model, where
     * the mark information is digitally signed. The digital signature can be
     * directly validated by the server using the public key of the external
     * party that created the signed mark using its private key. This model is
     * supported using the &lt;smd:signedMark&gt; and
     * &lt;smd:encodedSignedMark&gt; elements.
     */
    signedMark
  }

  /**
   * Possible check forms supported by the phase.
   */
  public static enum CheckForm implements java.io.Serializable,Cloneable {
    /**
     * Indicates support for the Claims Check Form, which defines a new
     * command called the Claims Check Command that is used to determine
     * whether or not there are any matching trademarks, in the specified
     * launch phase, for each domain name passed in the command.
     */
    claims,

    /**
     * Indicates support for the Availability Check Form, which extends the
     * Domain Check Command to specify which launch phase to use to check the
     * availability for each domain name passed in the command.
     */
    availability,
    /**
     * Indicates support for the Trademark Check Form, which defines a new
     * command called the Trademark Check Command that is used to determine
     * whether or not there are any matching trademarks for each domain name
     * passed in the command, independent of the active launch phase.
     */
    trademark
  }

  /**
   * Possible create forms supported by the phase.
   */
  public static enum CreateForm implements java.io.Serializable,Cloneable {
    /**
     * Indicates support for the Sunrise Create Form, which is an extension of
     * the Domain Create Command to include the verifiable trademark
     * information that the server uses to match against the domain name to
     * authorize the domain create.
     */
    sunrise,

    /**
     * Indicates support for the Claims Create Form, which is an extension of
     * the Domain Create Command to include information related to the
     * registrant's acceptance of the Claims Notice.
     */
    claims,
    /**
     * Indicates support for the General Create Form, which is an extension of
     * the Domain Create Command to specify the target launch phase for the
     * domain create.
     */
    general,

    /**
     * Indicates support for the Mixed Create Form, where a mix of create
     * forms is supported. For example, the Sunrise Create Form and the Claims
     * Create Form is supported in a single command by including both the
     * verified trademark information and the information related to the
     * registrant's acceptance of the Claims Notice.
     */
    mixed
  }

  /**
   * Category for logging
   */
      private static Logger cat = LoggerFactory.getLogger(EPPLaunchPolicyPhase.class);
        

  /**
   * Constant for the phase local name
   */
  public static final String ELM_LOCALNAME = "phase";

  /**
   * Constant for the phase qualified name (prefix and local name)
   */
  public static final String ELM_NAME = EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_LOCALNAME;

  /**
   * XML Element Name of {@code startDate} attribute.
   */
  private final static String ELM_START_DATE = "startDate";

  /**
   * XML Element Name of {@code endDate} attribute.
   */
  private final static String ELM_END_DATE = "endDate";

  /**
   * XML Element Name of {@code validatePhase} attribute.
   */
  private final static String ELM_VALIDATE_PHASE = "validatePhase";

  /**
   * XML Element Name of {@code validatorId} list attributes.
   */
  private final static String ELM_VALIDATOR_ID = "validatorId";

  /**
   * XML Element Name of {@code pendingCreate} attribute.
   */
  private final static String ELM_PENDING_CREATE = "pendingCreate";

  /**
   * XML Element Name of {@code markValidations} attribute list items.
   */
  private final static String ELM_MARK_VALIDATION = "markValidation";

  /**
   * XML Element Name of {@code maxMarks} attribute list items.
   */
  private final static String ELM_MAX_MARKS = "maxMarks";

  /**
   * XML Element Name of {@code marksSupported} attribute list items.
   */
  private final static String ELM_MARK_SUPPORTED = "markSupported";

  /**
   * XML Element Name of {@code signedMarksSupported} attribute list items.
   */
  private final static String ELM_SIGNED_MARK_SUPPORTED = "signedMarkSupported";

  /**
   * XML Element Name of {@code encodedSignedMarksSupported} attribute list
   * items.
   */
  private final static String ELM_ENCODED_SIGNED_MARK_SUPPORTED = "encodedSignedMarkSupported";

  /**
   * XML Element Name of {@code checkForms} attribute list items.
   */
  private final static String ELM_CHECK_FORM = "checkForm";

  /**
   * XML Element Name of {@code createForms} attribute list items.
   */
  private final static String ELM_CREATE_FORM = "createForm";

  /**
   * XML Element Name of {@code createValidateType} attribute.
   */
  private final static String ELM_CREATE_VALIDATE_TYPE = "createValidateType";

  /**
   * Phase type attribute name
   */
  private static final String ATTR_TYPE = "type";

  /**
   * OPTIONAL attribute name that can define a sub-phase or the full name of
   * the phase type when the phase type has the "custom" value.
   */
  private static final String ATTR_NAME = "name";

  /**
   * OPTIONAL attribute name that defines how the phase operates with the
   * following possible values and with the default value of {@link Mode#fcfs}.
   */
  private static final String ATTR_MODE = "mode";

  /**
   * Launch phase name using one of the {@link Phase} constants.
   */
  private Phase phase;

  /**
   * OPTIONAL "name" attribute that can define a sub-phase or the full name of
   * the phase when the phase has the {@link Phase#custom} value.
   */
  private String name;

  /**
   * OPTIONAL attribute that defines how the phase operates with the following
   * possible values and with the default value of {@link Mode#fcfs}.
   */
  private Mode mode = Mode.fcfs;

  /**
   * The start date and time for the phase.
   */
  private Date startDate;

  /**
   * The OPTIONAL end date and time for the phase.
   */
  private Date endDate;

  /**
   * OPTIONAL boolean value that indicates whether the server validates the
   * phase provided by the client in the &lt;launch:phase&gt; element.
   */
  private Boolean validatePhase;

  /**
   * Zero or more &lt;lp:validatorId&gt; elements that define the supported
   * Validator Identifier values for the phase. An example is the reserved
   * Validator Identifier of "tmch".
   */
  private List<String> validatorIds = new ArrayList<String>();

  /**
   * Zero or more &lt;lp:status&gt; elements that defines the supported launch
   * status values, in precedence order, for the phase.
   */
  private List<EPPLaunchPolicyPhaseStatus> statuses = new ArrayList<EPPLaunchPolicyPhaseStatus>();

  /**
   * An OPTIONAL boolean value that indicates that the server will place the
   * Launch Application or the Launch Registration in the "pendingCreate"
   * status as specified in [RFC5731].
   */
  private Boolean pendingCreate;

  /**
   * An OPTIONAL element that defines the poll messaging policy for the phase.
   */
  private EPPLaunchPolicyPollPolicy pollPolicy;

  /**
   * Zero to four &lt;lp:markValidation&gt; elements that defines the supported
   * Mark Validation Models supported by the phase.
   */
  private List<MarkValidation> markValidations = new ArrayList<MarkValidation>();

  /**
   * An OPTIONAL maximum number of marks per domain name for the phase.
   */
  private Integer maxMarks;

  /**
   * Zero or more &lt;lp:markSupported&gt; elements that defines the XML
   * namespace of the marks that are supported in the phase. For example, the
   * XML namespace "urn:ietf:params:xml:ns:mark-1.0" for [RFC7848].
   */
  private List<String> marksSupported = new ArrayList<String>();

  /**
   * Zero or more &lt;lp:signedMarkSupported&gt; elements that defines the XML
   * namespace of the signed marks that are supported in the phase. For
   * example, the XML namespace "urn:ietf:params:xml:ns:signedMark-1.0" for
   * [RFC7848].
   */
  private List<String> signedMarksSupported = new ArrayList<String>();

  /**
   * Zero or more &lt;lp:encodedSignedMarkSupported&gt; elements that defines
   * the XML namespace of the encoded signed marks that are supported in the
   * phase. For example, the XML namespace
   * "urn:ietf:params:xml:ns:signedMark-1.0" for [RFC7848].
   */
  private List<String> encodedSignedMarksSupported = new ArrayList<String>();

  /**
   * Zero to three &lt;lp:checkForm&gt; elements that defines the supported
   * check forms.
   */
  private List<CheckForm> checkForms = new ArrayList<CheckForm>();

  /**
   * Zero or more &lt;lp:infoPhase&gt; elements that defines the possible
   * &lt;launch:phase&gt; values that can be passed by the client in the phase.
   * The &lt;lp:infoPhase&gt; supports the "type" and "name" attributes defined
   * for the &lt;lp:phase&gt; element.
   */
  private List<EPPLaunchPolicyInfoPhase> infoPhases = new ArrayList<EPPLaunchPolicyInfoPhase>();

  /**
   * Zero to three &lt;lp:createForm&gt; elements that defines the supported
   * create forms.
   */
  private List<CreateForm> createForms = new ArrayList<CreateForm>();

  /**
   * OPTIONAL boolean value that indicates whether the server validates the
   * OPTIONAL &lt;launch:create&gt; "type" attribute.
   */
  private Boolean createValidateType;

  /**
   * {@code EPPLaunchPolicyPhase} default constructor.
   */
  public EPPLaunchPolicyPhase() {
  }

  /**
   * {@code EPPLaunchPolicyPhase} constructor that takes the required set of
   * attributes.
   *
   * @param aPhase
   *           The launch phase
   * @param aStartDate
   *           Start date and time for the phase.
   */
  public EPPLaunchPolicyPhase(Phase aPhase, Date aStartDate) {
    this.phase = aPhase;
    this.startDate = aStartDate;
  }

  /**
   * {@code EPPLaunchPolicyPhase} constructor that takes attributes.
   *
   * @param aPhase
   *           The launch phase
   * @param aName
   *           The sub-phase name or the custom name if {@code aPhase} is
   *           {@link Phase#custom}. Set to {@code null} if undefined.
   * @param aMode
   *           Phase operation mode. Setting to {@code null} will set the mode
   *           ot the default of {@link Mode#fcfs}.
   * @param aStartDate
   *           Start date and time for the phase.
   * @param aEndDate
   *           OPTIONAL end date and time for the phase. Set to {@code null} if
   *           undefined.
   * @param aValidatePhase
   *           OPTIONAL boolean value that indicates whether the server
   *           validates the phase provided by the client in the
   *           &lt;launch:phase&gt; element. Set to {@code null} if undefined.
   * @param aValidatorIds
   *           List of validator identifiers.
   * @param aStatuses
   *           List of supported phase statuses
   * @param aPendingCreate
   *           OPTIONAL boolean value that indicates that the server will place
   *           the Launch Application or the Launch Registration in the
   *           "pendingCreate" status as specified in [RFC5731]. Set to
   *           {@code null} if undefined.
   * @param aPollPolicy
   *           An OPTIONAL element that defines the poll messaging policy for
   *           the phase. Set to {@code null} if undefined.
   * @param aMarkValidations
   *           Supported mark validation models. Set to {@code null} if
   *           undefined.
   * @param aMaxMarks
   *           OPTIONAL maximum number of marks per domain name for the phase.
   *           Set to {code null} if undefined.
   * @param aMarksSupported
   *           Supported mark XML namespaces. Set to {@code null} if undefined.
   * @param aSignedMarksSupported
   *           Supported signed mark XML namespaces. Set to {@code null} if
   *           undefined.
   * @param aEncodedSignedMarksSupported
   *           Supported encoded signed mark XML namespaces. Set to
   *           {@code null} if undefined.
   * @param aCheckForms
   *           Supported check forms. Set to {@code null} if undefined.
   * @param aCreateForms
   *           Supported create forms. Set to {@code null} if undefined.
   * @param aCreateValidateType
   *           OPTIONAL boolean value that indicates whether the server
   *           validates the OPTIONAL &lt;launch:create&gt; "type" attribute.
   *           Set to {@code null} if undefined.
   */
  public EPPLaunchPolicyPhase(Phase aPhase, String aName, Mode aMode, Date aStartDate, Date aEndDate,
        Boolean aValidatePhase, List<String> aValidatorIds, List<EPPLaunchPolicyPhaseStatus> aStatuses,
        Boolean aPendingCreate, EPPLaunchPolicyPollPolicy aPollPolicy, List<MarkValidation> aMarkValidations,
        Integer aMaxMarks, List<String> aMarksSupported, List<String> aSignedMarksSupported,
        List<String> aEncodedSignedMarksSupported, List<CheckForm> aCheckForms, List<CreateForm> aCreateForms,
        Boolean aCreateValidateType) {
    this.phase = aPhase;
    this.name = aName;
    this.setMode(aMode);
    this.startDate = aStartDate;
    this.endDate = aEndDate;
    this.validatePhase = aValidatePhase;
    this.setValidatorIds(aValidatorIds);
    this.setStatuses(aStatuses);
    this.pendingCreate = aPendingCreate;
    this.pollPolicy = aPollPolicy;
    this.setMarkValidations(aMarkValidations);
    this.maxMarks = aMaxMarks;
    this.setMarksSupported(aMarksSupported);
    this.setSignedMarksSupported(aSignedMarksSupported);
    this.setEncodedSignedMarksSupported(aEncodedSignedMarksSupported);
    this.setCheckForms(aCheckForms);
    this.setCreateForms(aCreateForms);
    this.createValidateType = aCreateValidateType;
  }

  /**
   * Clone {@code EPPLaunchPolicyPhase} instance.
   *
   * @return clone of {@code EPPLaunchPolicyPhase}
   *
   * @exception CloneNotSupportedException
   *               standard Object.clone exception
   */
  @Override
  public Object clone() throws CloneNotSupportedException {
    EPPLaunchPolicyPhase clone = null;

    clone = (EPPLaunchPolicyPhase) super.clone();

    // Validator Ids
    if (this.validatorIds != null) {
      clone.validatorIds = (List) ((ArrayList) this.validatorIds).clone();
    }

    // Statuses
    if (this.statuses != null) {
      clone.statuses = (List) ((ArrayList) this.statuses).clone();
    }

    // Mark Validation Models
    if (this.markValidations != null) {
      clone.markValidations = (List) ((ArrayList) this.markValidations).clone();
    }

    // Marks Supported
    if (this.marksSupported != null) {
      clone.marksSupported = (List) ((ArrayList) this.marksSupported).clone();
    }

    // Signed Marks Supported
    if (this.signedMarksSupported != null) {
      clone.signedMarksSupported = (List) ((ArrayList) this.signedMarksSupported).clone();
    }

    // Encoded Signed Marks Supported
    if (this.encodedSignedMarksSupported != null) {
      clone.encodedSignedMarksSupported = (List) ((ArrayList) this.encodedSignedMarksSupported).clone();
    }

    // Check Forms
    if (this.checkForms != null) {
      clone.checkForms = (List) ((ArrayList) this.checkForms).clone();
    }

    // Info Phases
    if (this.infoPhases != null) {
      clone.infoPhases = (List) ((ArrayList) this.infoPhases).clone();
    }

    // Create Forms
    if (this.createForms != null) {
      clone.createForms = (List) ((ArrayList) this.createForms).clone();
    }

    return clone;
  }

  /**
   * Validate the state of the {@code EPPLaunchPolicyPhase} instance. A valid
   * state means that all of the required attributes have been set. If
   * validateState returns without an exception, the state is valid. If the
   * state is not valid, the {@link EPPCodecException} will contain a
   * description of the error. throws EPPCodecException State error. This will
   * contain the name of the attribute that is not valid.
   *
   * @throws EPPCodecException On invalid state
   */
  public void validateState() throws EPPCodecException {
    if (!this.hasPhase()) {
      throw new EPPCodecException("phase required attribute is not set");
    }
    if (!this.hasStartDate()) {
      throw new EPPCodecException("startDate required attribute is not set");
    }
  }

  /**
   * Encode a DOM Element tree from the attributes of the
   * {@code EPPLaunchPolicyPhase} instance.
   *
   * @param aDocument
   *           - DOM Document that is being built. Used as an Element factory.
   *
   * @return Element - Root DOM Element representing the
   *         {@code EPPLaunchPolicyPhase} instance.
   *
   * @exception EPPEncodeException
   *               - Unable to encode {@code EPPLaunchPolicyPhase} instance.
   */
  @Override
  public Element encode(Document aDocument) throws EPPEncodeException {

    if (aDocument == null) {
      throw new EPPEncodeException("aDocument is null" + " in EPPLaunchPolicyPhase.encode(Document)");
    }

    try {
      this.validateState();
    }
    catch (EPPCodecException e) {
      cat.error(this.getClass().getName() + ".encode(): Invalid state on encode: " + e);
      throw new EPPEncodeException("Invalid state on " + this.getClass().getName() + ".encode(): " + e);
    }

    Element root = aDocument.createElementNS(EPPLaunchPolicyExtFactory.NS, ELM_NAME);

    // Phase
    root.setAttribute(ATTR_TYPE, this.phase.toString());

    // Name
    if (this.hasName()) {
      root.setAttribute(ATTR_NAME, this.name);
    }

    // Mode
    root.setAttribute(ATTR_MODE, this.mode.toString());

    // Start Date
    EPPUtil.encodeTimeInstant(aDocument, root, this.startDate, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_START_DATE);

    // End Date
    EPPUtil.encodeTimeInstant(aDocument, root, this.endDate, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_END_DATE);

    // Validate Phase
    EPPUtil.encodeBoolean(aDocument, root, this.validatePhase, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_VALIDATE_PHASE);

    // Validator Ids
    EPPUtil.encodeList(aDocument, root, this.validatorIds, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_VALIDATOR_ID);

    // Statuses
    EPPUtil.encodeCompList(aDocument, root, this.statuses);

    // Pending Create
    EPPUtil.encodeBoolean(aDocument, root, this.pendingCreate, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_PENDING_CREATE);

    // Poll Policy
    EPPUtil.encodeComp(aDocument, root, this.pollPolicy);

    // Mark Validation Models
    EPPUtil.encodeList(aDocument, root, this.markValidations, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_MARK_VALIDATION);

    // Max Marks
    EPPUtil.encodeInteger(aDocument, root, this.maxMarks, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_MAX_MARKS);

    // Marks Supported
    EPPUtil.encodeList(aDocument, root, this.marksSupported, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_MARK_SUPPORTED);

    // Signed Marks Supported
    EPPUtil.encodeList(aDocument, root, this.signedMarksSupported, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_SIGNED_MARK_SUPPORTED);

    // Encoded Signed Marks Supported
    EPPUtil.encodeList(aDocument, root, this.encodedSignedMarksSupported, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_ENCODED_SIGNED_MARK_SUPPORTED);

    // Check Forms
    EPPUtil.encodeList(aDocument, root, this.checkForms, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_CHECK_FORM);

    // Info Phases
    EPPUtil.encodeCompList(aDocument, root, this.infoPhases);

    // Create Forms
    EPPUtil.encodeList(aDocument, root, this.createForms, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_CREATE_FORM);

    // Create Validate Type
    EPPUtil.encodeBoolean(aDocument, root, this.createValidateType, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyExtFactory.NS_PREFIX + ":" + ELM_CREATE_VALIDATE_TYPE);

    return root;
  }

  /**
   * Decode the {@code EPPLaunchPolicyPhase} element aElement DOM Element tree.
   *
   * @param aElement
   *           - Root DOM Element to decode {@code EPPLaunchPolicyPhase} from.
   *
   * @exception EPPDecodeException
   *               Unable to decode aElement
   */
  @Override
  public void decode(Element aElement) throws EPPDecodeException {

    // Phase
    this.phase = Phase.valueOf(EPPUtil.decodeStringAttr(aElement, ATTR_TYPE));

    // Name
    this.name = EPPUtil.decodeStringAttr(aElement, ATTR_NAME);

    // Mode
    String theModeStr = EPPUtil.decodeStringAttr(aElement, ATTR_MODE);
    if (theModeStr == null) {
      this.mode = Mode.fcfs;
    }
    else {
      this.mode = Mode.getMode(theModeStr);
    }

    // Start Date
    this.startDate = EPPUtil.decodeTimeInstant(aElement, EPPLaunchPolicyExtFactory.NS, ELM_START_DATE);

    // End Date
    this.endDate = EPPUtil.decodeTimeInstant(aElement, EPPLaunchPolicyExtFactory.NS, ELM_END_DATE);

    // Validate Phase
    this.validatePhase = EPPUtil.decodeBoolean(aElement, EPPLaunchPolicyExtFactory.NS, ELM_VALIDATE_PHASE);

    // Validator Ids
    this.validatorIds = EPPUtil.decodeList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_VALIDATOR_ID);

    // Statuses
    this.statuses = EPPUtil.decodeCompList(aElement, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyPhaseStatus.ELM_LOCALNAME, EPPLaunchPolicyPhaseStatus.class);

    // Pending Create
    this.pendingCreate = EPPUtil.decodeBoolean(aElement, EPPLaunchPolicyExtFactory.NS, ELM_PENDING_CREATE);

    // Poll Policy
    this.pollPolicy = (EPPLaunchPolicyPollPolicy) EPPUtil.decodeComp(aElement, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyPollPolicy.ELM_LOCALNAME, EPPLaunchPolicyPollPolicy.class);

    // Mark Validation Models
    this.markValidations = EPPUtil.decodeEnumList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_MARK_VALIDATION,
          MarkValidation.class);

    // Max Marks
    this.maxMarks = EPPUtil.decodeInteger(aElement, EPPLaunchPolicyExtFactory.NS, ELM_MAX_MARKS);

    // Marks Supported
    this.marksSupported = EPPUtil.decodeList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_MARK_SUPPORTED);

    // Signed Marks Supported
    this.signedMarksSupported = EPPUtil.decodeList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_SIGNED_MARK_SUPPORTED);

    // Encoded Signed Marks Supported
    this.encodedSignedMarksSupported = EPPUtil.decodeList(aElement, EPPLaunchPolicyExtFactory.NS,
          ELM_ENCODED_SIGNED_MARK_SUPPORTED);

    // Check Forms
    this.checkForms = EPPUtil.decodeEnumList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_CHECK_FORM, CheckForm.class);

    // Info Phases
    this.infoPhases = EPPUtil.decodeCompList(aElement, EPPLaunchPolicyExtFactory.NS,
          EPPLaunchPolicyInfoPhase.ELM_LOCALNAME, EPPLaunchPolicyInfoPhase.class);

    // Create Forms
    this.createForms = EPPUtil.decodeEnumList(aElement, EPPLaunchPolicyExtFactory.NS, ELM_CREATE_FORM,
          CreateForm.class);

    // Create Validate Type
    this.createValidateType = EPPUtil.decodeBoolean(aElement, EPPLaunchPolicyExtFactory.NS, ELM_CREATE_VALIDATE_TYPE);
  }

  /**
   * implements a deep {@code EPPLaunchPolicyPhase} compare.
   *
   * @param aObject
   *           {@code EPPLaunchPolicyPhase} instance to compare with
   *
   * @return {@code true} if equal; {@code false} otherwise
   */
  @Override
  public boolean equals(Object aObject) {
    if (!(aObject instanceof EPPLaunchPolicyPhase)) {
      return false;
    }

    EPPLaunchPolicyPhase other = (EPPLaunchPolicyPhase) aObject;

    // Phase
    if (!EqualityUtil.equals(this.phase, other.phase)) {
      cat.error("EPPLaunchPolicyPhase.equals(): phase not equal");
      return false;
    }

    // Name
    if (!EqualityUtil.equals(this.name, other.name)) {
      cat.error("EPPLaunchPolicyPhase.equals(): name not equal");
      return false;
    }

    // Mode
    if (!EqualityUtil.equals(this.mode, other.mode)) {
      cat.error("EPPLaunchPolicyPhase.equals(): mode not equal");
      return false;
    }

    // Start Date
    if (!EqualityUtil.equals(this.startDate, other.startDate)) {
      cat.error("EPPLaunchPolicyPhase.equals(): startDate not equal");
      return false;
    }

    // End Date
    if (!EqualityUtil.equals(this.endDate, other.endDate)) {
      cat.error("EPPLaunchPolicyPhase.equals(): endDate not equal");
      return false;
    }

    // Validate Phase
    if (!EqualityUtil.equals(this.validatePhase, other.validatePhase)) {
      cat.error("EPPLaunchPolicyPhase.equals(): validatePhase not equal");
      return false;
    }

    // Validator Ids
    if (!((this.validatorIds == null) ? (other.validatorIds == null)
          : EPPUtil.equalLists(this.validatorIds, other.validatorIds))) {
      cat.error("EPPLaunchPolicyPhase.equals(): validatorIds not equal");
      return false;
    }

    // Statuses
    if (!((this.statuses == null) ? (other.statuses == null) : EPPUtil.equalLists(this.statuses, other.statuses))) {
      cat.error("EPPLaunchPolicyPhase.equals(): statuses not equal");
      return false;
    }

    // Pending Create
    if (!EqualityUtil.equals(this.pendingCreate, other.pendingCreate)) {
      cat.error("EPPLaunchPolicyPhase.equals(): pendingCreate not equal");
      return false;
    }

    // Poll Policy
    if (!EqualityUtil.equals(this.pollPolicy, other.pollPolicy)) {
      cat.error("EPPLaunchPolicyPhase.equals(): pollPolicy not equal");
      return false;
    }

    // Mark Validation Models
    if (!((this.markValidations == null) ? (other.markValidations == null)
          : EPPUtil.equalLists(this.markValidations, other.markValidations))) {
      cat.error("EPPLaunchPolicyPhase.equals(): markValidations not equal");
      return false;
    }

    // Max Marks
    if (!EqualityUtil.equals(this.maxMarks, other.maxMarks)) {
      cat.error("EPPLaunchPolicyPhase.equals(): maxMarks not equal");
      return false;
    }

    // Marks Supported
    if (!((this.marksSupported == null) ? (other.marksSupported == null)
          : EPPUtil.equalLists(this.marksSupported, other.marksSupported))) {
      cat.error("EPPLaunchPolicyPhase.equals(): marksSupported not equal");
      return false;
    }

    // Signed Marks Supported
    if (!((this.signedMarksSupported == null) ? (other.signedMarksSupported == null)
          : EPPUtil.equalLists(this.signedMarksSupported, other.signedMarksSupported))) {
      cat.error("EPPLaunchPolicyPhase.equals(): signedMarksSupported not equal");
      return false;
    }

    // Encoded Signed Marks Supported
    if (!((this.encodedSignedMarksSupported == null) ? (other.encodedSignedMarksSupported == null)
          : EPPUtil.equalLists(this.encodedSignedMarksSupported, other.encodedSignedMarksSupported))) {
      cat.error("EPPLaunchPolicyPhase.equals(): encodedSignedMarksSupported not equal");
      return false;
    }

    // Check Forms
    if (!((this.checkForms == null) ? (other.checkForms == null)
          : EPPUtil.equalLists(this.checkForms, other.checkForms))) {
      cat.error("EPPLaunchPolicyPhase.equals(): checkForms not equal");
      return false;
    }

    // Info Phases
    if (!((this.infoPhases == null) ? (other.infoPhases == null)
          : EPPUtil.equalLists(this.infoPhases, other.infoPhases))) {
      cat.error("EPPLaunchPolicyPhase.equals(): infoPhases not equal");
      return false;
    }

    // Create Forms
    if (!((this.createForms == null) ? (other.createForms == null)
          : EPPUtil.equalLists(this.createForms, other.createForms))) {
      cat.error("EPPLaunchPolicyPhase.equals(): createForms not equal");
      return false;
    }

    // Create Validate Type
    if (!EqualityUtil.equals(this.createValidateType, other.createValidateType)) {
      cat.error("EPPLaunchPolicyPhase.equals(): createValidateType not equal");
      return false;
    }

    return true;
  }

  /**
   * Implementation of {@code Object.toString}, which will result in an
   * indented XML {@code String} representation of the concrete
   * {@code EPPCodecComponent}.
   *
   * @return Indented XML {@code String} if successful; {@code ERROR}
   *         otherwise.
   */
  @Override
  public String toString() {
    return EPPUtil.toString(this);
  }

  /**
   * Returns the XML namespace associated with the {@code EPPCodecComponent}.
   *
   * @return XML namespace for the {@code EPPCodecComponent}.
   */
  @Override
  public String getNamespace() {
    return EPPLaunchPolicyExtFactory.NS;
  }

  /**
   * Is the phase defined?
   *
   * @return {@code true} if the phase is defined; {@code false} otherwise.
   */
  public boolean hasPhase() {
    return (this.phase != null ? true : false);
  }

  /**
   * Gets the phase value.
   *
   * @return {@link Phase} enumerated value if set; {@code null} otherwise.
   */
  public Phase getPhase() {
    return this.phase;
  }

  /**
   * Sets the phase value.
   *
   * @param aPhase
   *           Sets the phase value.
   */
  public void setPhase(Phase aPhase) {
    this.phase = aPhase;
  }

  /**
   * Is the name defined?
   *
   * @return {@code true} if the name is defined; {@code false} otherwise.
   */
  public boolean hasName() {
    return (this.name != null ? true : false);
  }

  /**
   * Gets the OPTIONAL phase name or sub-phase name.
   *
   * @return The phase name or sub-phase name if defined; {@code null}
   *         otherwise.
   */
  public String getName() {
    return this.name;
  }

  /**
   * Sets the OPTIONAL phase name or sub-phase name.
   *
   * @param aName
   *           Phase name
   */
  public void setName(String aName) {
    this.name = aName;
  }

  /**
   * Gets the mode value.
   *
   * @return {@link Mode} enumerated value, with the default value of
   *         {@link Mode#fcfs}.
   */
  public Mode getMode() {
    return this.mode;
  }

  /**
   * Sets the mode value.
   *
   * @param aMode
   *           Sets the phase value. If {@code null} the default value of
   *           {@link Mode#fcfs}.
   */
  public void setMode(Mode aMode) {
    if (aMode == null) {
      this.mode = Mode.fcfs;
    }
    else {
      this.mode = aMode;
    }
  }

  /**
   * Is the start date defined?
   *
   * @return {@code true} if the start date is defined; {@code false}
   *         otherwise.
   */
  public boolean hasStartDate() {
    return (this.startDate != null ? true : false);
  }

  /**
   * Get the start date and time for the phase.
   *
   * @return Start date and time for the phase.
   */
  public Date getStartDate() {
    return this.startDate;
  }

  /**
   * Set start date and time for the phase.
   *
   * @param aStartDate
   *           Start date and time for the phase.
   */
  public void setCreateDate(Date aStartDate) {
    this.startDate = aStartDate;
  }

  /**
   * Is the end date defined?
   *
   * @return {@code true} if the start date is defined; {@code false}
   *         otherwise.
   */
  public boolean hasEndDate() {
    return (this.endDate != null ? true : false);
  }

  /**
   * Get the OPTIONAL end date and time for the phase.
   *
   * @return End date and time for the phase if defined; {@code null}
   *         otherwise.
   */
  public Date getEndDate() {
    return this.endDate;
  }

  /**
   * Set end date and time for the phase.
   *
   * @param aEndDate
   *           End date and time for the phase. Set to {@code null} if
   *           undefined.
   */
  public void setEndDate(Date aEndDate) {
    this.endDate = aEndDate;
  }

  /**
   * Is the validate phase flag defined?
   *
   * @return <code>true</code> if the validate phase flag is defined;
   *         <code>false</code> otherwise.
   */
  public boolean hasValidatePhase() {
    return (this.validatePhase != null ? true : false);
  }

  /**
   * Gets the OPTIONAL boolean value that indicates whether the server
   * validates the phase provided by the client in the &lt;launch:phase&gt;
   * element.
   *
   * @return <code>true</code> or <code>false</code> indicating whether the
   *         server validates the phase provided by the client in the
   *         &lt;launch:phase&gt; element if defined; {@code null} otherwise.
   */
  public Boolean getValidatePhase() {
    return this.validatePhase;
  }

  /**
   * Sets the OPTIONAL boolean flag that indicates whether the server validates
   * the phase provided by the client in the &lt;launch:phase&gt; element.
   *
   * @param aValidatePhase
   *           <code>true</code> or <code>false</code> indicating whether the
   *           server validates the phase provided by the client in the
   *           &lt;launch:phase&gt; element. Set to {@code null} if undefined.
   */
  public void setValidatePhase(Boolean aValidatePhase) {
    this.validatePhase = aValidatePhase;
  }

  /**
   * Is the validator identifier list defined?
   *
   * @return {@code true} if the validator identifier list is defined;
   *         {@code false} otherwise.
   */
  public boolean hasValidatorIds() {
    return (this.validatorIds != null && !this.validatorIds.isEmpty() ? true : false);
  }

  /**
   * Gets the validator identifier list.
   *
   * @return Validator identifiers
   */
  public List<String> getValidatorIds() {
    return this.validatorIds;
  }

  /**
   * Sets the validator identifier list.
   *
   * @param aValidatorIds
   *           List of validator identifiers.
   */
  public void setValidatorIds(List<String> aValidatorIds) {
    if (aValidatorIds == null) {
      this.validatorIds = new ArrayList<String>();
    }
    else {
      this.validatorIds = aValidatorIds;
    }
  }

  /**
   * Add a validator identifier to the list of supported Validator Identifier
   * values for the phase.
   *
   * @param aValidatorId
   *           Validator identifier to the list of supported Validator
   *           Identifier values for the phase.
   */
  public void addValidatorId(String aValidatorId) {
    if (aValidatorId == null) {
      this.validatorIds = new ArrayList<String>();
    }
    this.validatorIds.add(aValidatorId);
  }

  /**
   * Is the status list defined?
   *
   * @return {@code true} if the status list is defined; {@code false}
   *         otherwise.
   */
  public boolean hasStatuses() {
    return (this.statuses != null && !this.statuses.isEmpty() ? true : false);
  }

  /**
   * Gets the status list. which defines the supported launch status values.
   *
   * @return Supported launch statuses
   */
  public List<EPPLaunchPolicyPhaseStatus> getStatuses() {
    return this.statuses;
  }

  /**
   * Sets the status list. which defines the supported launch status values.
   *
   * @param aStatuses
   *           List of supported launch statuses
   */
  public void setStatuses(List<EPPLaunchPolicyPhaseStatus> aStatuses) {
    if (aStatuses == null) {
      this.statuses = new ArrayList<EPPLaunchPolicyPhaseStatus>();
    }
    else {
      this.statuses = aStatuses;
    }
  }

  /**
   * Adds a status to the status list. which defines the supported launch
   * status values.
   *
   * @param aStatus
   *           Supported status to add to the supported launch status list.
   */
  public void addStatus(EPPLaunchPolicyPhaseStatus aStatus) {
    if (this.statuses == null) {
      this.statuses = new ArrayList<EPPLaunchPolicyPhaseStatus>();
    }
    this.statuses.add(aStatus);
  }

  /**
   * Is the pending create flag defined?
   *
   * @return <code>true</code> if the pending create flag is defined;
   *         <code>false</code> otherwise.
   */
  public boolean hasPendingCreate() {
    return (this.pendingCreate != null ? true : false);
  }

  /**
   * Gets the OPTIONAL boolean value that indicates that the server will place
   * the Launch Application or the Launch Registration in the "pendingCreate"
   * status as specified in [RFC5731].
   *
   * @return <code>true</code> or <code>false</code> indicating that the server
   *         will place the Launch Application or the Launch Registration in
   *         the "pendingCreate" status as specified in [RFC5731] if defined;
   *         {@code null} otherwise.
   */
  public Boolean getPendingCreate() {
    return this.pendingCreate;
  }

  /**
   * Sets the OPTIONAL boolean flag that indicates that the server will place
   * the Launch Application or the Launch Registration in the "pendingCreate"
   * status as specified in [RFC5731].
   *
   * @param aPendingCreate
   *           <code>true</code> or <code>false</code> indicating that the
   *           server will place the Launch Application or the Launch
   *           Registration in the "pendingCreate" status as specified in
   *           [RFC5731]. Set to {@code null} if undefined.
   */
  public void setPendingCreate(Boolean aPendingCreate) {
    this.pendingCreate = aPendingCreate;
  }

  /**
   * Is the poll policy defined?
   *
   * @return {@code true} if the poll policy is defined; {@code false}
   *         otherwise.
   */
  public boolean hasPollPolicy() {
    return (this.pollPolicy != null ? true : false);
  }

  /**
   * Gets the poll policy value.
   *
   * @return {@link EPPLaunchPolicyPollPolicy} instance if defined;
   *         {@code null} otherwise.
   */
  public EPPLaunchPolicyPollPolicy getPollPolicy() {
    return this.pollPolicy;
  }

  /**
   * Sets the poll policy value.
   *
   * @param aPollPolicy
   *           Sets the poll policy value.
   */
  public void setPollPolicy(EPPLaunchPolicyPollPolicy aPollPolicy) {
    this.pollPolicy = aPollPolicy;
  }

  /**
   * Is the mark validation list defined?
   *
   * @return {@code true} if the mark validation is defined; {@code false}
   *         otherwise.
   */
  public boolean hasMarkValidations() {
    return (this.markValidations != null && !this.markValidations.isEmpty() ? true : false);
  }

  /**
   * Gets the mark validation list. which defines the supported mark validation
   * models in the phase.
   *
   * @return Supported mark validation models statuses
   */
  public List<MarkValidation> getMarkValidations() {
    return this.markValidations;
  }

  /**
   * Sets the mark validation list. which defines the supported mark validation
   * models in the phase.
   *
   * @param aMarkValidations
   *           List of supported mark validation models
   */
  public void setMarkValidations(List<MarkValidation> aMarkValidations) {
    if (aMarkValidations == null) {
      this.markValidations = new ArrayList<MarkValidation>();
    }
    else {
      this.markValidations = aMarkValidations;
    }
  }

  /**
   * Adds a mark validation model to the mark validation list. which defines
   * the supported mark validation models in the phase.
   *
   * @param aMarkValidation
   *           Supported mark validation model to add to the mark validation
   *           list.
   */
  public void addMarkValidation(MarkValidation aMarkValidation) {
    if (this.markValidations == null) {
      this.markValidations = new ArrayList<MarkValidation>();
    }
    this.markValidations.add(aMarkValidation);
  }

  /**
   * Is the max marks defined?
   *
   * @return <code>true</code> if the max marks is defined; <code>false</code>
   *         otherwise.
   */
  public boolean hasMaxMarks() {
    return (this.maxMarks != null ? true : false);
  }

  /**
   * Gets the OPTIONAL maximum number of marks per domain name for the phase.
   *
   * @return Maximum number of marks per domain name for the phase if defined;
   *         {@code null} otherwise.
   */
  public Integer getMaxMarks() {
    return this.maxMarks;
  }

  /**
   * Sets the OPTIONAL maximum number of marks per domain name for the phase.
   *
   * @param aMaxMarks
   *           Maximum number of marks per domain name for the phase. Set to
   *           {@code null} if undefined.
   */
  public void setMaxMarks(Integer aMaxMarks) {
    this.maxMarks = aMaxMarks;
  }

  /**
   * Is the marks supported list defined?
   *
   * @return {@code true} if the marks supported list is defined; {@code false}
   *         otherwise.
   */
  public boolean hasMarksSupported() {
    return (this.marksSupported != null && !this.marksSupported.isEmpty() ? true : false);
  }

  /**
   * Gets the marks supported list, which is the list of XML namespaces of the
   * marks that are supported in the phase.
   *
   * @return XML namespaces of the marks supported by the phase.
   */
  public List<String> getMarksSupported() {
    return this.marksSupported;
  }

  /**
   * Sets the marks supported list, which is the list of XML namespaces of the
   * marks that are supported in the phase.
   *
   * @param aMarksSupported
   *           List of supported mark XML namespaces
   */
  public void setMarksSupported(List<String> aMarksSupported) {
    if (aMarksSupported == null) {
      this.marksSupported = new ArrayList<String>();
    }
    else {
      this.marksSupported = aMarksSupported;
    }
  }

  /**
   * Add a mark XML namespace to the list of supported mark XML namespaces.
   *
   * @param aMarkSupported
   *           XML namespace of the mark that is supported in the phase.
   */
  public void addMarkSupported(String aMarkSupported) {
    if (this.marksSupported == null) {
      this.marksSupported = new ArrayList<String>();
    }
    this.marksSupported.add(aMarkSupported);
  }

  /**
   * Is the signed marks supported list defined?
   *
   * @return {@code true} if the signed marks supported list is defined;
   *         {@code false} otherwise.
   */
  public boolean hasSignedMarksSupported() {
    return (this.signedMarksSupported != null && !this.signedMarksSupported.isEmpty() ? true : false);
  }

  /**
   * Gets the signed marks supported list, which is the list of XML namespaces
   * of the signed marks that are supported in the phase.
   *
   * @return XML namespaces of the signed marks supported by the phase.
   */
  public List<String> getSignedMarksSupported() {
    return this.signedMarksSupported;
  }

  /**
   * Sets the signed marks supported list, which is the list of XML namespaces
   * of the signed marks that are supported in the phase.
   *
   * @param aSignedMarksSupported
   *           List of supported signed mark XML namespaces
   */
  public void setSignedMarksSupported(List<String> aSignedMarksSupported) {
    if (aSignedMarksSupported == null) {
      this.signedMarksSupported = new ArrayList<String>();
    }
    else {
      this.signedMarksSupported = aSignedMarksSupported;
    }
  }

  /**
   * Add a signed mark XML namespace to the list of supported signed mark XML
   * namespaces.
   *
   * @param aSignedMarkSupported
   *           XML namespace of the signed mark that is supported in the phase.
   */
  public void addSignedMarkSupported(String aSignedMarkSupported) {
    if (this.signedMarksSupported == null) {
      this.signedMarksSupported = new ArrayList<String>();
    }
    this.signedMarksSupported.add(aSignedMarkSupported);
  }

  /**
   * Is the encoded signed marks supported list defined?
   *
   * @return {@code true} if the encoded signed marks supported list is
   *         defined; {@code false} otherwise.
   */
  public boolean hasEncodedSignedMarksSupported() {
    return (this.encodedSignedMarksSupported != null && !this.encodedSignedMarksSupported.isEmpty() ? true : false);
  }

  /**
   * Gets the encoded signed marks supported list, which is the list of XML
   * namespaces of the encoded signed marks that are supported in the phase.
   *
   * @return XML namespaces of the encoded signed marks supported by the phase.
   */
  public List<String> getEncodedSignedMarksSupported() {
    return this.encodedSignedMarksSupported;
  }

  /**
   * Sets the encoded signed marks supported list, which is the list of XML
   * namespaces of the encoded signed marks that are supported in the phase.
   *
   * @param aEncodedSignedMarksSupported
   *           List of supported encoded signed mark XML namespaces
   */
  public void setEncodedSignedMarksSupported(List<String> aEncodedSignedMarksSupported) {
    if (aEncodedSignedMarksSupported == null) {
      this.encodedSignedMarksSupported = new ArrayList<String>();
    }
    else {
      this.encodedSignedMarksSupported = aEncodedSignedMarksSupported;
    }
  }

  /**
   * Add an encoded signed mark XML namespace to the list of supported encoded
   * signed mark XML namespaces.
   *
   * @param aEncodedSignedMarkSupported
   *           XML namespace of the signed mark that is supported in the phase.
   */
  public void addEncodedSignedMarkSupported(String aEncodedSignedMarkSupported) {
    if (this.encodedSignedMarksSupported == null) {
      this.encodedSignedMarksSupported = new ArrayList<String>();
    }
    this.encodedSignedMarksSupported.add(aEncodedSignedMarkSupported);
  }

  /**
   * Is the check form list defined?
   *
   * @return {@code true} if the check form list is defined; {@code false}
   *         otherwise.
   */
  public boolean hasCheckForms() {
    return (this.checkForms != null && !this.checkForms.isEmpty() ? true : false);
  }

  /**
   * Gets the check form list. which defines the supported check forms in the
   * phase.
   *
   * @return Supported check forms
   */
  public List<CheckForm> getCheckForms() {
    return this.checkForms;
  }

  /**
   * Sets the check form list. which defines the supported check forms in the
   * phase.
   *
   * @param aCheckForms
   *           List of supported check forms
   */
  public void setCheckForms(List<CheckForm> aCheckForms) {
    if (aCheckForms == null) {
      this.checkForms = new ArrayList<CheckForm>();
    }
    else {
      this.checkForms = aCheckForms;
    }
  }

  /**
   * Adds a check form to the check form list. which defines the supported
   * check forms in the phase.
   *
   * @param aCheckForm
   *           Supported check form to add to the check form list.
   */
  public void addCheckForm(CheckForm aCheckForm) {
    if (this.checkForms == null) {
      this.checkForms = new ArrayList<CheckForm>();
    }
    this.checkForms.add(aCheckForm);
  }

  /**
   * Is the info phase list defined?
   *
   * @return {@code true} if the info phase list is defined; {@code false}
   *         otherwise.
   */
  public boolean hasInfoPhases() {
    return (this.infoPhases != null && !this.infoPhases.isEmpty() ? true : false);
  }

  /**
   * Gets the info phase list. which defines the supported info phase values.
   *
   * @return Supported info launch phases
   */
  public List<EPPLaunchPolicyInfoPhase> getInfoPhases() {
    return this.infoPhases;
  }

  /**
   * Sets the info phase list. which defines the supported info phase values.
   *
   * @param aInfoPhases
   *           List of supported info phase values.
   */
  public void setInfoPhases(List<EPPLaunchPolicyInfoPhase> aInfoPhases) {
    if (aInfoPhases == null) {
      this.infoPhases = new ArrayList<EPPLaunchPolicyInfoPhase>();
    }
    else {
      this.infoPhases = aInfoPhases;
    }
  }

  /**
   * Adds an info phase to the info phase list, which defines the supported
   * info phase values.
   *
   * @param aInfoPhase
   *           Supported info phase to add to the supported info phase list.
   */
  public void addInfoPhase(EPPLaunchPolicyInfoPhase aInfoPhase) {
    if (this.infoPhases == null) {
      this.infoPhases = new ArrayList<EPPLaunchPolicyInfoPhase>();
    }
    this.infoPhases.add(aInfoPhase);
  }

  /**
   * Is the create form list defined?
   *
   * @return {@code true} if the create form list is defined; {@code false}
   *         otherwise.
   */
  public boolean hasCreateForms() {
    return (this.createForms != null && !this.createForms.isEmpty() ? true : false);
  }

  /**
   * Gets the create form list. which defines the supported create forms in the
   * phase.
   *
   * @return Supported create forms
   */
  public List<CreateForm> getCreateForms() {
    return this.createForms;
  }

  /**
   * Sets the create form list. which defines the supported create forms in the
   * phase.
   *
   * @param aCreateForms
   *           List of supported create forms
   */
  public void setCreateForms(List<CreateForm> aCreateForms) {
    if (aCreateForms == null) {
      this.createForms = new ArrayList<CreateForm>();
    }
    else {
      this.createForms = aCreateForms;
    }
  }

  /**
   * Adds a create form to the create form list. which defines the supported
   * create forms in the phase.
   *
   * @param aCreateForm
   *           Supported create form to add to the create form list.
   */
  public void addCreateForm(CreateForm aCreateForm) {
    if (this.createForms == null) {
      this.createForms = new ArrayList<CreateForm>();
    }
    this.createForms.add(aCreateForm);
  }

  /**
   * Is the create validate type flag defined?
   *
   * @return <code>true</code> if the create validate type flag is defined;
   *         <code>false</code> otherwise.
   */
  public boolean hasCreateValidateType() {
    return (this.createValidateType != null ? true : false);
  }

  /**
   * Gets the OPTIONAL boolean value that indicates whether the server
   * validates the OPTIONAL &lt;launch:create&gt; "type" attribute.
   *
   * @return <code>true</code> or <code>false</code> indicating whether the
   *         server validates the OPTIONAL &lt;launch:create&gt; "type"
   *         attribute. if defined; {@code null} otherwise.
   */
  public Boolean getCreateValidateType() {
    return this.createValidateType;
  }

  /**
   * Sets the OPTIONAL boolean value that indicates whether the server
   * validates the OPTIONAL &lt;launch:create&gt; "type" attribute.
   *
   * @param aCreateValidateType
   *           <code>true</code> or <code>false</code> indicating whether the
   *           server validates the OPTIONAL &lt;launch:create&gt; "type"
   *           attribute. Set to {@code null} if undefined.
   */
  public void setCreateValidateType(Boolean aCreateValidateType) {
    this.createValidateType = aCreateValidateType;
  }

}
