/**************************************************************************
 *                                                                        *
 * The information in this document is proprietary to VeriSign, Inc.      *
 * It may not be used, reproduced or disclosed without the written        *
 * approval of VeriSign.                                                  *
 *                                                                        *
 * VERISIGN PROPRIETARY & CONFIDENTIAL INFORMATION                        *
 *                                                                        *
 *                                                                        *
 * Copyright (c) 2011 VeriSign, Inc.  All rights reserved.                *
 *                                                                        *
 *************************************************************************/

package com.verisign.epp.codec.coaext;

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;


/**
 * EPPCodecComponent that encodes and decodes a COA Attr Tag.
 * <p>
 * Title: EPP 1.0 Client Object Attribute - Attr
 * </p>
 * <p>
 * Description: Each EPPCoaExtAttr object represents a single Client Object Attribute. As
 * such it contains a single key-value pair, represented by one EPPCoaExtKey and
 * one EPPCoaExtValue element. <br>
 * As XML, is is represented by a &lt;coa:attr&gt; element
 * containing a single &lt;coa:key&gt; element and a single &lt;coa:value&gt; element.
 * </p>
 * <p>
 * Copyright: Copyright (c) 2011
 * </p>
 * <p>
 * Company: VeriSign
 * </p>
 * 
 * @author jfaust
 * @version 1.0
 */
public class EPPCoaExtAttr implements EPPCodecComponent {

	/**
	 * Serial version id - increment this if the structure changes.
	 */
	private static final long serialVersionUID = 1L;

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

	/**
	 * Constant for the key tag
	 */
	public static final String ELM_NAME = "coa:attr";

	/**
	 * The key in this key/value pair.
	 */
	private EPPCoaExtKey key = null;

	/**
	 * The value in this key/value pair.
	 */
	private EPPCoaExtValue value = null;


	/**
	 * Default constructor
	 */
	public EPPCoaExtAttr () {
	}


	/**
	 * Convenience constructor specifying the key and value as arguments.
	 * 
	 * @param aKey Key of COA
	 * @param aValue Value of COA
	 */
	public EPPCoaExtAttr ( String aKey, String aValue ) {
		this.key = new EPPCoaExtKey( aKey );
		this.value = new EPPCoaExtValue( aValue );
	}


	/**
	 * A deep clone of the EPPCoaExtAttr.
	 * 
	 * @see java.lang.Object#clone()
	 */
	public Object clone () throws CloneNotSupportedException {

		EPPCoaExtAttr theClone = (EPPCoaExtAttr) super.clone();

		if ( this.getKey() != null ) {
			theClone.setKey( (EPPCoaExtKey) this.getKey().clone() );
		}

		if ( this.getValue() != null ) {
			theClone.setValue( (EPPCoaExtValue) this.getValue().clone() );
		}

		return theClone;
	}


	/**
	 * A deep comparison of this to another EPPCoaExtAttr.
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals ( Object aComp ) {

		if ( !(aComp instanceof EPPCoaExtAttr) ) {
			return false;
		}

		EPPCoaExtAttr theComp = (EPPCoaExtAttr) aComp;
		
		if (this.getKey() == null) {
			return false;
		}

		if ( !this.getKey().equals( theComp.getKey() ) ) {
			return false;
		}

		if ( this.getValue() == null && theComp.getValue() != null) {
			return false;
		}
		
		if ( !this.getValue().equals( theComp.getValue() ) ) {
			return false;
		}

		return true;
	}


	/**
	 * Decode the EPPCoaExtAttr element by decoding its &lt;coa:key&gt; and &lt;coa:value&gt;
	 * subelements.
	 * 
	 * @see com.verisign.epp.codec.gen.EPPCodecComponent#decode(org.w3c.dom.Element)
	 */
	public void decode ( Element aElement ) throws EPPDecodeException {

		this.key =
				(EPPCoaExtKey) EPPUtil.decodeComp( aElement, EPPCoaExtFactory.NS,
						EPPCoaExtKey.ELM_NAME, EPPCoaExtKey.class );

		this.value =
				(EPPCoaExtValue) EPPUtil.decodeComp( aElement, EPPCoaExtFactory.NS,
						EPPCoaExtValue.ELM_NAME, EPPCoaExtValue.class );

	}


	/**
	 * Encode an EPPCoaExtAttr by encoding its EPPCoaExtKey and EPPCoaExtValue
	 * attributes.
	 * 
	 * @see com.verisign.epp.codec.gen.EPPCodecComponent#encode(org.w3c.dom.Document)
	 */
	public Element encode ( Document aDocument ) throws EPPEncodeException {
		
		if ( aDocument == null ) {
			throw new EPPEncodeException( "aDocument is null"
					+ " in EPPCoaExtAttr.encode(Document)" );
		}
		
		try {
			// Validate States
			validateState();
		}
		catch ( EPPCodecException e ) {
			cat.error( "EPPCoaExtAttr.encode(): Invalid state on encode: " + e );
			throw new EPPEncodeException( "EPPCoaExtAttr invalid state: " + e );
		}

		// coa:attr
		Element root = aDocument.createElementNS( EPPCoaExtFactory.NS, ELM_NAME );

		root.appendChild( this.key.encode( aDocument ) );

		root.appendChild( this.value.encode( aDocument ) );

		return root;
	}


	/**
	 * Validate the state of the {@code EPPCoaExtAttr} 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 {@code 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
	 *         Thrown if the instance is in an invalid state
	 */
	private void validateState () throws EPPCodecException {
		if ( this.key == null ) {
			throw new EPPCodecException(
					"EPPCoaExtAttr required element key is not set" );
		}

		if ( this.value == null ) {
			throw new EPPCodecException(
					"EPPCoaExtAttr required element value is not set" );
		}

	}


	/**
	 * Gets the key of the COA.
	 * @return Key of the COA
	 */
	public EPPCoaExtKey getKey () {
		return key;
	}


	/**
	 * Sets the key of the COA.
	 * 
	 * @param aKey Key of the COA
	 */
	public void setKey ( EPPCoaExtKey aKey ) {
		this.key = aKey;
	}


	/**
	 * Gets the value of the COA.
	 * 
	 * @return Value of the COA 
	 */
	public EPPCoaExtValue getValue () {
		return this.value;
	}


	/**
	 * Sets the value of the COA.
	 * 
	 * @param aValue Value of the COA
	 */
	public void setValue ( EPPCoaExtValue aValue ) {
		this.value = aValue;
	}

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

}
