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

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 Host &lt;host:chkData&gt; response to a
 * {@code EPPHostCheckCmd}. When a &lt;check&gt; command has been processed
 * successfully, the EPP &lt;resData&gt; element MUST contain a child
 * &lt;host:chkData&gt; element that identifies the host namespace and the
 * location of the host schema. The &lt;host:chkData&gt; element contains one or
 * more &lt;host:cd&gt; elements that contain the following child elements: <br>
 * 
 * <ul>
 * <li>A &lt;host:name&gt; element that contains the fully qualified name of the
 * queried host 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;host: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). Use {@code getCheckResults} and {@code setCheckResults} to get and
 * set the elements.</li>
 * </ul>
 *
 * @see com.verisign.epp.codec.host.EPPHostCheckCmd
 * @see com.verisign.epp.codec.host.EPPHostCheckResult
 */
public class EPPHostCheckResp 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 = EPPHostMapFactory.NS_PREFIX + ":" + ELM_LOCALNAME;

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

  /**
   * {@code EPPHostCheckResp} default constructor. It will set results
   * attribute to an empty {@code Vector}.
   */
  public EPPHostCheckResp() {
    results = new Vector<EPPHostCheckResult>();
  }

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

    results = new Vector<EPPHostCheckResult>();
    results.addElement(aResult);
  }

  /**
   * {@code EPPHostCheckResp} constructor that will set the result of multiple
   * hosts.
   *
   * @param aTransId
   *           Transaction Id associated with response.
   * @param aResults
   *           Vector of EPPCheckHostResult instances.
   */
  public EPPHostCheckResp(EPPTransId aTransId, Vector<EPPHostCheckResult> aResults) {
    super(aTransId);

    results = aResults;
  }

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

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

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

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

    return root;
  }

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

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

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

    EPPHostCheckResp thePingData = (EPPHostCheckResp) aObject;

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

    return true;
  }

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

    clone.results = (Vector<EPPHostCheckResult>) results.clone();

    for (int i = 0; i < this.results.size(); i++) {
      clone.results.setElementAt((EPPHostCheckResult) (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.
   */
  public String toString() {
    return EPPUtil.toString(this);
  }

  /**
   * Set the results of a {@code EPPHostCheckResp} Response. There is one
   * {@code EPPCheckHostResult} instance in {@code someResults} for each host
   * requested in the {@code EPPHostCheckCmd} Command.
   *
   * @param aResults
   *           Vector of {@code EPPHostCheckResult} instances.
   */
  public void setCheckResults(Vector<EPPHostCheckResult> aResults) {
    results = aResults;
  }

  /**
   * Get the results of a EPPHostCheckResp Response. There is one
   * {@code EPPCheckHostResult} instance in {@code someResults} for each host
   * requested in the {@code EPPCheckHostResult} Command.
   *
   * @return Vector of {@code EPPHostResult} instances.
   */
  public Vector<EPPHostCheckResult> getCheckResults() {
    return results;
  }

}
