/***********************************************************
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.domain;

import java.util.Vector;

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

import com.verisign.epp.codec.gen.EPPDecodeException;
import com.verisign.epp.codec.gen.EPPEncodeException;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.gen.EPPTransId;
import com.verisign.epp.codec.gen.EPPUtil;

/**
 * Represents an EPP Domain &lt;domain:chkData&gt; response to a
 * {@code EPPDomainCheckCmd}. When a &lt;check&gt; command has been processed
 * successfully, the EPP &lt;resData&gt; element MUST contain a child
 * &lt;domain:chkData&gt; element that identifies the domain namespace and the
 * location of the domain schema. The &lt;domain:chkData&gt; elements that
 * contain the following child elements: <br>
 *
 * <ul>
 * <li>A &lt;domain:name&gt; element that contains the fully qualified name of
 * the queried domain object. This element MUST contain an "avail" attribute
 * whose value indicates object availability at the moment the &lt;check&gt;
 * command was completed. A value of "1" or "true" menas that the object is
 * availabe. A value of "0" or "false" means that the object is not available.
 * </li>
 * <li>An OPTIONAL &lt;domain:reason&gt; element that MAY be provided when an
 * object is not available for provisioning. If present, this element contains
 * server-specific text to help explain why the object is unavailable. This text
 * MUST be represented in the response language previously negotiated with the
 * client; an OPTIONAL "lang" attribute MAY be present to identify the language
 * if the negotiated value is something other that a default value of "en"
 * (English).</li>
 * </ul>
 *
 * @see com.verisign.epp.codec.domain.EPPDomainCheckCmd
 * @see com.verisign.epp.codec.domain.EPPDomainCheckResult
 */
public class EPPDomainCheckResp extends EPPResponse {
  /**
   * XML local name for {@code EPPDomainCheckResp}.
   */
  public static final String ELM_LOCALNAME = "chkData";

  /**
   * XML Element Name of {@code EPPDomainCheckResp} root element.
   */
  public static final String ELM_NAME = EPPDomainMapFactory.NS_PREFIX + ":" + ELM_LOCALNAME;

  /**
   * {@code Vector} of {@code EPPDomainCheckResult} instances.
   */
  private Vector<EPPDomainCheckResult> results = new Vector<EPPDomainCheckResult>();

  /**
   * {@code EPPDomainCheckResp} default constructor. It will set results
   * attribute to an empty {@code Vector}.
   */
  public EPPDomainCheckResp() {
  }

  /**
   * {@code EPPDomainCheckResp} constructor that sets the transaction
   * identifier.
   *
   * @param aTransId
   *           Transaction Id associated with response.
   */
  public EPPDomainCheckResp(EPPTransId aTransId) {
    super(aTransId);
  }

  /**
   * {@code EPPDomainCheckResp} constructor that will set the result of an
   * individual domain.
   *
   * @param aTransId
   *           Transaction Id associated with response.
   * @param aResult
   *           Result of a single domain name.
   */
  public EPPDomainCheckResp(EPPTransId aTransId, EPPDomainCheckResult aResult) {
    super(aTransId);

    this.results.addElement(aResult);
  }

  /**
   * {@code EPPDomainCheckResp} constructor that will set the result of
   * multiple domains.
   *
   * @param aTransId
   *           Transaction Id associated with response.
   * @param someResults
   *           Vector of EPPDomainCheckResult instances.
   */
  public EPPDomainCheckResp(EPPTransId aTransId, Vector<EPPDomainCheckResult> someResults) {
    super(aTransId);

    this.results = someResults;
  }

  /**
   * Get the EPP response type associated with {@code EPPDomainCheckResp}.
   *
   * @return EPPDomainCheckResp.ELM_NAME
   */
  @Override
  public String getType() {
    return ELM_NAME;
  }

  /**
   * Get the EPP command Namespace associated with {@code EPPDomainCheckResp}.
   *
   * @return {@code EPPDomainMapFactory.NS}
   */
  @Override
  public String getNamespace() {
    return EPPDomainMapFactory.NS;
  }

  /**
   * Compare an instance of {@code EPPDomainCheckResp} with this instance.
   *
   * @param aObject
   *           Object to compare with.
   *
   * @return {@code true} if equal; {@code false} otherwise.
   */
  @Override
  public boolean equals(Object aObject) {
    if (!(aObject instanceof EPPDomainCheckResp)) {
      return false;
    }

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

    EPPDomainCheckResp theCheckData = (EPPDomainCheckResp) aObject;

    // results
    if (!EPPUtil.equalVectors(this.results, theCheckData.results)) {
      return false;
    }

    return true;
  }

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

    clone.results = (Vector<EPPDomainCheckResult>) this.results.clone();

    for (int i = 0; i < this.results.size(); i++) {
      clone.results.setElementAt((EPPDomainCheckResult) (this.results.elementAt(i)).clone(), i);
    }

    return clone;
  }

  /**
   * 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);
  }

  /**
   * Adds a result to the list of check results.
   *
   * @param aResult
   *           Result to add.
   */
  public void addResult(EPPDomainCheckResult aResult) {
    if (aResult == null) {
      return;
    }

    if (this.results == null) {
      this.results = new Vector<EPPDomainCheckResult>();
    }

    this.results.add(aResult);
  }

  /**
   * Set the results of a {@code EPPDomainCheckResp} Response. There is one
   * {@code EPPDomainCheckResult} instance in {@code someResults} for each
   * domain requested in the {@code EPPDomainCheckCmd} Command.
   *
   * @param aResults
   *           Vector of {@code EPPDomainCheckResult} instances.
   */
  public void setCheckResults(Vector<EPPDomainCheckResult> aResults) {
    this.results = aResults;
  }

  /**
   * Get the results of a {@code EPPDomainCheckResp} Response. There is one
   * {@code EPPDomainCheckResult} instance in {@code someResults} for each
   * domain requested in the {@code EPPDomainCheckResult} Command.
   *
   * @return {@code Vector} of {@code EPPDomainCheckResult} instances.
   */
  public Vector<EPPDomainCheckResult> getCheckResults() {
    return this.results;
  }

  /**
   * Encode a DOM Element tree from the attributes of the
   * {@code EPPDomainCheckResp} instance.
   *
   * @param aDocument
   *           DOM Document that is being built. Used as an Element factory.
   *
   * @return Element Root DOM Element representing the
   *         {@code EPPDomainCheckResp} instance.
   *
   * @exception EPPEncodeException
   *               Unable to encode {@code EPPDomainCheckResp} instance.
   */
  @Override
  protected Element doEncode(Document aDocument) throws EPPEncodeException {
    Element root = aDocument.createElementNS(EPPDomainMapFactory.NS, ELM_NAME);

    // Results
    EPPUtil.encodeCompVector(aDocument, root, this.results);

    return root;
  }

  /**
   * Decode the {@code EPPDomainCheckResp} attributes from the aElement DOM
   * Element tree.
   *
   * @param aElement
   *           Root DOM Element to decode {@code EPPDomainCheckResp} from.
   *
   * @exception EPPDecodeException
   *               Unable to decode aElement
   */
  @Override
  protected void doDecode(Element aElement) throws EPPDecodeException {
    // Results
    this.results = EPPUtil.decodeCompVector(aElement, EPPDomainMapFactory.NS, EPPDomainCheckResult.ELM_NAME,
          EPPDomainCheckResult.class);
  }

}
