/***********************************************************
Copyright (C) 2004 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.gen;


import org.w3c.dom.Document;
import org.w3c.dom.Element;


/**
 * The EPP &lt;transfer&gt; command provides a query operation that allows a
 * client to determine real-time status of pending and completed transfer
 * requests.  The elements needed to identify an object that is the subject of
 * a transfer request are object-specific, so the child elements of the
 * &lt;transfer&gt; query command are specified using the EPP extension
 * framework.  In addition to the standard EPP command elements, the
 * &lt;transfer&gt; command SHALL contain an {@code op} attribute with
 * value {@code query}, and the following child elements: An
 * object-specific &lt;obj:transfer&gt; element that identifies the object whose
 * transfer status is requested. <br>
 * <br>
 * {@code EPPTransferCmd} is an abstract EPP command class that represents
 * a transfer operation.   A command mapping transfer command extends
 * {@code EPPTransferCmd}.   For example,
 * {@code EPPDomainTransferCmd} is a {@code EPPTransferCmd} that
 * implements the Domain Transfer Command Mapping.  The different types of
 * transfer operations can  be one of the {@code EPPCommand.OP_}
 * constants.
 */
public abstract class EPPTransferCmd extends EPPCommand {
  /** XML Element Name of {@code EPPTransferCmd} root element. */
  final static String ELM_NAME = "transfer";

  /**
   * XML Attribute Name for the {@code getOp()} extension value.   For
   * example, {@code EPPCommand.OP_APPROVE}.
   */
  private final static String ATTR_OP = "op";

  /**
   * Operation "op" associated with the {@code EPPTransferCmd}.  This
   * should be equal to  one of the {@code EPPCommand.OP_} constants.
   */
  protected String op = null;

  /**
   * Default constructor.  Will set Authorization Id to null.
   */
  public EPPTransferCmd() {
    op = null;
  }


  /**
   * {@code EPPTransferCmd} that takes all required attributes as
   * arguments.
   *
   * @param aTransId Transaction Id associated with command.
   * @param aOp One of the {@code EPPCommand.OP_} constants associated
   *      with the transfer command.
   */
  public EPPTransferCmd(String aTransId, String aOp) {
    super(aTransId);

    op = aOp;
  }


  /**
   * Gets the EPP command type associated with EPPTransferCmd.
   *
   * @return {@code EPPCommand.TYPE_TRANSFER}
   */
  public String getType() {
    return EPPCommand.TYPE_TRANSFER;
  }


  /**
   * Gets the EPP command operation attribute associated with
   * {@code EPPTransferCmd}.
   *
   * @return One of the {@code EPPCommand.OP_} constants associated with
   *       the transfer command.
   */
  public String getOp() {
    return op;
  }


  /**
   * Sets the EPP command operation attribute associated with
   * {@code EPPTransferCmd}.
   *
   * @param aOp One of the {@code EPPCommand.OP_} constants associated
   *      with the transfer command.
   */
  public void setOp(String aOp) {
    op = aOp;
  }


  /**
   * Compares an instance of EPPTransferCmd with this instance.
   *
   * @param aObject Object to compare with.
   *
   * @return {@code true} if equal; {@code false} otherwise
   */
  public boolean equals(Object aObject) {
    EPPTransferCmd theTransfer = (EPPTransferCmd) aObject;

    // EPPCommand
    if (!super.equals(aObject)) {
      return false;
    }

    // Operation
    if (
      !(
          (op == null) ? (theTransfer.op == null)
                   : op.equals(theTransfer.op)
        )) {
      return false;
    }

    return true;
  }


  /**
   * Encodes a DOM Element tree from the attributes of the
   * {@code EPPTransferCmd} instance.  This method is a member of the
   * Template Design Pattern. {@code EPPCommand.encode} is a
   * <i>Template Method</i> and this method is a <i>Primitive Operation</i>
   * within the Template Method Design Pattern.
   *
   * @param aDocument DOM Document that is being built.  Used as an Element
   *      factory.
   *
   * @return Root DOM Element representing the {@code EPPTransferCmd}
   *       instance.
   *
   * @exception EPPEncodeException Unable to encode
   *        {@code EPPTransferCmd} instance.
   */
  protected Element doGenEncode(Document aDocument) throws EPPEncodeException {
    // <transfer> Element
    Element root = aDocument.createElementNS(EPPCodec.NS, ELM_NAME);

    if (op == null) {
      throw new EPPEncodeException("EPPTransferCmd op attribute is null");
    }

    root.setAttribute(ATTR_OP, op);

    // Command Mapping
    Element mapElement = doEncode(aDocument);

    if (mapElement != null) {
      root.appendChild(mapElement);
    }

    return root;
  }


  /**
   * Decodes the {@code EPPTransferCmd} attributes from the
   * {@code aElement} DOM Element tree.   This method is a member of
   * the Template Design Pattern. {@code EPPCommand.decode} is a
   * <i>Template Method</i> and this method is a <i>Primitive Operation</i>
   * within the Template Method Design Pattern.
   *
   * @param aElement Root DOM Element to decode {@code EPPTransferCmd}
   *      from.
   *
   * @exception EPPDecodeException Unable to decode aElement
   */
  protected void doGenDecode(Element aElement) throws EPPDecodeException {
    op = aElement.getAttribute(ATTR_OP);

    if (op == null) {
      throw new EPPDecodeException("EPPTransferCmd requires an \""
                     + ATTR_OP + "\" attribute");
    }

    // Command Mapping
    doDecode(EPPUtil.getFirstElementChild(aElement));
  }


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

    clone = (EPPTransferCmd) super.clone();

    return clone;
  }


  /**
   * Must be defined by {@code EPPTransferCmd} extensions (Command
   * Mappings) to encode the attributes to a DOM Element tree.
   * {@code doGenEncode} is a <i>Template Method</i> and this method is
   * a <i>Primitive Operation</i> within the Template Method Design Pattern.
   *
   * @param aDocument DOM Document that is being built.  Used as an Element
   *      factory.
   *
   * @return Root DOM Element representing the EPPTransferCmd extension
   *       instance.
   *
   * @exception EPPEncodeException Unable to encode EPPTransferCmd extension
   *        instance.
   */
  protected abstract Element doEncode(Document aDocument)
                 throws EPPEncodeException;

  /**
   * Must be defined by {@code EPPTransferCmd} extensions (Command
   * Mappings) to decode     the attributes to a DOM Element tree.
   * {@code doGenDecode} is a <i>Template Method</i>     and this
   * method is a <i>Primitive Operation</i> within the Template Method
   * Design Pattern.
   *
   * @param aElement Root DOM Element representing the
   *      {@code EPPTransferCmd} extension instance.
   *
   * @exception EPPDecodeException Unable to decode {@code aElement}.
   */
  protected abstract void doDecode(Element aElement)
                throws EPPDecodeException;
}
