/***********************************************************
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 org.w3c.dom.Document;
//----------------------------------------------
//
// imports...
//
//----------------------------------------------
// W3C Imports
import org.w3c.dom.Element;
import org.w3c.dom.Text;

// EPP Imports
import com.verisign.epp.codec.gen.EPPCodecComponent;
import com.verisign.epp.codec.gen.EPPDecodeException;
import com.verisign.epp.codec.gen.EPPEncodeException;
import com.verisign.epp.codec.gen.EPPUtil;

/**
 * Represents a domain contact. The valid contact types are defined by the
 * {@code EPPDomainContact.TYPE_} constants. A contact has a type and a
 * name that must be known to the EPP Server.
 */
public class EPPDomainContact implements EPPCodecComponent {

  /**
   * XML local name for {@code EPPDomainContact}.
   */
  public static final String ELM_LOCALNAME = "contact";

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

  /**
   * Administrative Domain Contact
   */
  public final static String TYPE_ADMINISTRATIVE = "admin";

  /**
   * Billing Domain Contact
   */
  public final static String TYPE_BILLING = "billing";

  /**
   * Technical Domain Contact
   */
  public final static String TYPE_TECHNICAL = "tech";

  /**
   * XML tag name for the {@code type} attribute.
   */
  private final static String ATTR_TYPE = "type";

  /**
   * Type of contact defined by a {@code EPPDomainContact.TYPE_} constant.
   */
  private String type;

  /**
   * Name of contact.
   */
  private String name;

  /**
   * Default constructor for EPPDomainContact. The attribute default to
   * {@code null} and must be set before invoking {@code encode}.
   */
  public EPPDomainContact() {
    this.name = null;
    this.type = null;
  }

  /**
   * EPPDomainContact which takes all attributes as arguments (name, type).
   *
   * @param aName
   *           Contact Name
   * @param aType
   *           Contact Type, which should be a
   *           {@code EPPDomainContact.TYPE_} constant.
   */
  public EPPDomainContact(String aName, String aType) {
    this.name = aName;
    this.type = aType;
  }

  /**
   * Gets the contact name
   *
   * @return Contact Name
   */
  public String getName() {
    return this.name;
  }

  /**
   * Sets the contact name.
   *
   * @param aName
   *           Contact Name
   */
  public void setName(String aName) {
    this.name = aName;
  }

  /**
   * Gets the contact type.
   *
   * @return contact type using one of the {@code TYPE} constants.
   */
  public String getType() {
    return this.type;
  }

  /**
   * Sets the contact type to one of the {@code EPPDomainContact.TYPE_}
   * constants.
   *
   * @param aType
   *           {@code EPPDomainContact.TYPE_} constant.
   */
  public void setType(String aType) {
    this.type = aType;
  }

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

    // Type
    if (this.type == null) {
      throw new EPPEncodeException("EPPDomainContact type is null on call to encode");
    }

    root.setAttribute(ATTR_TYPE, this.type);

    // Name
    if (this.name == null) {
      throw new EPPEncodeException("EPPDomainContact name is null on call to encode");
    }

    Text textNode = aDocument.createTextNode(this.name);
    root.appendChild(textNode);

    return root;
  }

  /**
   * Decode the EPPDomainContact attributes from the aElement DOM Element tree.
   *
   * @param aElement
   *           - Root DOM Element to decode EPPDomainContact from.
   *
   * @exception EPPDecodeException
   *               - Unable to decode aElement.
   */
  @Override
  public void decode(Element aElement) throws EPPDecodeException {
    // Type
    this.type = aElement.getAttribute(ATTR_TYPE);

    // Name
    this.name = aElement.getFirstChild().getNodeValue();
  }

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

    EPPDomainContact theComp = (EPPDomainContact) aObject;

    // Name
    if (!((this.name == null) ? (theComp.name == null) : this.name.equals(theComp.name))) {
      return false;
    }

    // Type
    if (!((this.type == null) ? (theComp.type == null) : this.type.equals(theComp.type))) {
      return false;
    }

    return true;
  }

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

    clone = (EPPDomainContact) super.clone();

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

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