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

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.verisign.epp.codec.gen.EPPCodecComponent;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.org.EPPOrgCheckCmd;
import com.verisign.epp.codec.org.EPPOrgCheckResp;
import com.verisign.epp.codec.org.EPPOrgContact;
import com.verisign.epp.codec.org.EPPOrgCreateCmd;
import com.verisign.epp.codec.org.EPPOrgCreateResp;
import com.verisign.epp.codec.org.EPPOrgDeleteCmd;
import com.verisign.epp.codec.org.EPPOrgInfoCmd;
import com.verisign.epp.codec.org.EPPOrgInfoResp;
import com.verisign.epp.codec.org.EPPOrgPostalDefinition;
import com.verisign.epp.codec.org.EPPOrgRole;
import com.verisign.epp.codec.org.EPPOrgStatus;
import com.verisign.epp.codec.org.EPPOrgUpdateCmd;

/**
 * <code>EPPOrg</code> is the primary client interface class used for the Org
 * EPP mapping. An instance of <code>EPPOrg</code> is created with an
 * initialized <code>EPPSession</code>, and can be used for more than one
 * request within a single thread. A set of setter methods are provided to set
 * the attributes before a call to one of the send action methods. The responses
 * returned from the send action methods are either instances of
 * <code>EPPResponse</code> or instances of response classes in the
 * <code>com.verisign.epp.codec.org</code> package.
 *
 * @see com.verisign.epp.codec.org.EPPOrgCheckResp
 * @see com.verisign.epp.codec.org.EPPOrgInfoResp
 * @see com.verisign.epp.codec.org.EPPOrgCreateResp
 */
public class EPPOrg {

	/** An instance of a session. */
	private EPPSession session = null;

	/** Transaction Id provided by client */
	private String transId = null;

	/**
	 * Extension objects associated with the command. This is a
	 * <code>Vector</code> of <code>EPPCodecComponent</code> objects.
	 */
	private Vector extensions = null;

	/**
	 * Org identifiers
	 */
	private List<String> orgIds = null;

	/**
	 * Parent Identifier
	 */
	private String parentId = null;

	/**
	 * One or two postal information elements.
	 */
	private List<EPPOrgPostalDefinition> postalInfo = null;

	/**
	 * Voice number
	 */
	private String voice = null;

	/**
	 * Voice Extension
	 */
	private String voiceExt = null;

	/**
	 * FAX number
	 */
	private String fax = null;

	/**
	 * FAX Extension
	 */
	private String faxExt = null;

	/**
	 * Email Address
	 */
	private String email = null;

	/**
	 * URL
	 */
	private String url = null;

	/**
	 * Org contacts
	 */
	private List<EPPOrgContact> contacts = null;

	/**
	 * Add Org contacts
	 */
	private List<EPPOrgContact> addContacts = null;

	/**
	 * Remove Org contacts
	 */
	private List<EPPOrgContact> remContacts = null;

	/**
	 * Org roles
	 */
	private List<EPPOrgRole> roles = null;

	/**
	 * Add Org roles
	 */
	private List<EPPOrgRole> addRoles = null;

	/**
	 * Remove Org roles
	 */
	private List<EPPOrgRole> remRoles = null;

	/**
	 * Org statuses
	 */
	private List<EPPOrgStatus> statuses = null;

	/**
	 * Add Org statuses
	 */
	private List<EPPOrgStatus> addStatuses = null;

	/**
	 * Remove Org statuses
	 */
	private List<EPPOrgStatus> remStatuses = null;

	/**
	 * Constructs an <code>EPPOrg</code> given an initialized EPP session.
	 *
	 * @param aSession
	 *           Server session to use.
	 */
	public EPPOrg(EPPSession aSession) {
		this.session = aSession;

		return;
	}

	/**
	 * Adds a command extension object.
	 *
	 * @param aExtension
	 *           command extension object associated with the command
	 */
	public void addExtension(EPPCodecComponent aExtension) {
		if (this.extensions == null) {
			this.extensions = new Vector();
		}

		this.extensions.addElement(aExtension);
	}

	/**
	 * Sets the command extension objects.
	 *
	 * @param aExtensions
	 *           command extension objects associated with the command
	 */
	public void setExtensions(Vector aExtensions) {
		this.extensions = aExtensions;
	}

	/**
	 * Gets the command extensions.
	 *
	 * @return <code>Vector</code> of concrete <code>EPPCodecComponent</code>
	 *         associated with the command if exists; <code>null</code>
	 *         otherwise.
	 */
	public Vector getExtensions() {
		return this.extensions;
	}

	/**
	 * Sets the client transaction identifier.
	 *
	 * @param aTransId
	 *           Client transaction identifier
	 */
	public void setTransId(String aTransId) {
		this.transId = aTransId;
	}

	/**
	 * Get the list of org identifiers.
	 * 
	 * @return {@code List} of org identifier {@code String}'s
	 */
	public List<String> getOrgIds() {
		return this.orgIds;
	}

	/**
	 * Adds a org identifier for use with a <code>send</code> method. Adding more
	 * than one org identifier is only supported by {@link #sendCheck()}.
	 *
	 * @param aOrgId
	 *           Org Identifier
	 */
	public void addOrgId(String aOrgId) {
		if (this.orgIds == null) {
			this.orgIds = new ArrayList<String>();
		}
		this.orgIds.add(aOrgId);
	}

	/**
	 * @return the parentId
	 */
	public String getParentId() {
		return this.parentId;
	}

	/**
	 * @param aParentId
	 *           the parentId to set
	 */
	public void setParentId(String aParentId) {
		this.parentId = aParentId;
	}

	/**
	 * Is there any postal information set?
	 * 
	 * @return <code>true</code> if there is at least one
	 *         {@link EPPOrgPostalDefinition} set in the postal information;
	 *         <code>false</code> otherwise.
	 */
	public boolean hasPostalInfo() {
		if (this.postalInfo != null && !this.postalInfo.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds a postal definition to the postal information for the org.
	 * 
	 * @param aPostalInfo
	 *           Postal definition to add to the postal information.
	 */
	public void addPostalInfo(EPPOrgPostalDefinition aPostalInfo) {
		if (this.postalInfo == null) {
			this.postalInfo = new ArrayList<EPPOrgPostalDefinition>();
		}
		this.postalInfo.add(aPostalInfo);
	}

	/**
	 * Gets the postal information for the org. There can be one or two
	 * {@link EPPOrgPostalDefinition} objects in the postal information list.
	 * 
	 * @return Postal information for the org
	 */
	public List<EPPOrgPostalDefinition> getPostalInfo() {
		return this.postalInfo;
	}

	/**
	 * Sets the postal information for the org. There can be one or two
	 * {@link EPPOrgPostalDefinition} objects in the postal information list.
	 * 
	 * @param aPostalInfo
	 *           Postal information for the org.
	 */
	public void setPostalInfo(List<EPPOrgPostalDefinition> aPostalInfo) {
		this.postalInfo = aPostalInfo;
	}

	/**
	 * @return the voice
	 */
	public String getVoice() {
		return this.voice;
	}

	/**
	 * @param aVoice
	 *           the voice to set
	 */
	public void setVoice(String aVoice) {
		this.voice = aVoice;
	}

	/**
	 * @return the voiceExt
	 */
	public String getVoiceExt() {
		return this.voiceExt;
	}

	/**
	 * @param aVoiceExt
	 *           the voiceExt to set
	 */
	public void setVoiceExt(String aVoiceExt) {
		this.voiceExt = aVoiceExt;
	}

	/**
	 * @return the fax
	 */
	public String getFax() {
		return this.fax;
	}

	/**
	 * @param aFax
	 *           the fax to set
	 */
	public void setFax(String aFax) {
		this.fax = aFax;
	}

	/**
	 * @return the faxExt
	 */
	public String getFaxExt() {
		return this.faxExt;
	}

	/**
	 * @param aFaxExt
	 *           the faxExt to set
	 */
	public void setFaxExt(String aFaxExt) {
		this.faxExt = aFaxExt;
	}

	/**
	 * @return the email
	 */
	public String getEmail() {
		return this.email;
	}

	/**
	 * @param aEmail
	 *           the email to set
	 */
	public void setEmail(String aEmail) {
		this.email = aEmail;
	}

	/**
	 * Gets the URL of the website of the org.
	 * 
	 * @return URL of the website of the org.
	 */
	public String getUrl() {
		return this.url;
	}

	/**
	 * Sets the URL of the website of the org.
	 * 
	 * @param aUrl
	 *           URL of the website of the org.
	 */
	public void setUrl(String aUrl) {
		this.url = aUrl;
	}

	/**
	 * Is there any contacts set?
	 * 
	 * @return <code>true</code> if there is at least one {@link EPPOrgContact}
	 *         set; <code>false</code> otherwise.
	 */
	public boolean hasContacts() {
		if (this.contacts != null && !this.contacts.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds a contact to the list of contacts.
	 * 
	 * @param aContact
	 *           Contact add to the list of contacts.
	 */
	public void addContact(EPPOrgContact aContact) {
		if (this.contacts == null) {
			this.contacts = new ArrayList<EPPOrgContact>();
		}
		this.contacts.add(aContact);
	}

	/**
	 * @return the contacts
	 */
	public List<EPPOrgContact> getContacts() {
		return this.contacts;
	}

	/**
	 * @param aContacts
	 *           the contacts to set
	 */
	public void setContacts(List<EPPOrgContact> aContacts) {
		this.contacts = aContacts;
	}

	/**
	 * Adds an add contact to the list of add contacts.
	 * 
	 * @param aContact
	 *           Contact to add to the list of add contacts.
	 */
	public void addAddContact(EPPOrgContact aContact) {
		if (this.addContacts == null) {
			this.addContacts = new ArrayList<EPPOrgContact>();
		}
		this.addContacts.add(aContact);
	}

	/**
	 * Gets the add contacts.
	 * 
	 * @return List of add contacts set.
	 */
	public List<EPPOrgContact> getAddContacts() {
		return this.addContacts;
	}

	/**
	 * Sets the add contacts.
	 * 
	 * @param aContacts
	 *           List of add contacts
	 */
	public void setAddContacts(List<EPPOrgContact> aContacts) {
		this.addContacts = aContacts;
	}

	/**
	 * Is there any remove contacts set?
	 * 
	 * @return <code>true</code> if there is at least one remove
	 *         {@link EPPOrgContact} set; <code>false</code> otherwise.
	 */
	public boolean hasRemContacts() {
		if (this.remContacts != null && !this.remContacts.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds a remove contact to the list of remove contacts.
	 * 
	 * @param aContact
	 *           Contact to add to the list of remove contacts.
	 */
	public void addRemContact(EPPOrgContact aContact) {
		if (this.remContacts == null) {
			this.remContacts = new ArrayList<EPPOrgContact>();
		}
		this.remContacts.add(aContact);
	}

	/**
	 * Gets the remove contacts.
	 * 
	 * @return List of remove contacts set.
	 */
	public List<EPPOrgContact> getRemContacts() {
		return this.remContacts;
	}

	/**
	 * Sets the remove contacts.
	 * 
	 * @param aContacts
	 *           List of remove contacts
	 */
	public void setRemContacts(List<EPPOrgContact> aContacts) {
		this.remContacts = aContacts;
	}

	/**
	 * Adds a role to the list of roles.
	 * 
	 * @param aRole
	 *           Role to add to the list of roles.
	 */
	public void addRole(EPPOrgRole aRole) {
		if (this.roles == null) {
			this.roles = new ArrayList<EPPOrgRole>();
		}
		this.roles.add(aRole);
	}

	/**
	 * Gets the list of roles
	 * 
	 * @return the roles
	 */
	public List<EPPOrgRole> getRoles() {
		return this.roles;
	}

	/**
	 * Sets the list of roles
	 * 
	 * @param aRoles
	 *           the roles to set
	 */
	public void setRoles(List<EPPOrgRole> aRoles) {
		this.roles = aRoles;
	}

	/**
	 * Is there any add roles set?
	 * 
	 * @return <code>true</code> if there is at least one add {@link EPPOrgRole}
	 *         set; <code>false</code> otherwise.
	 */
	public boolean hasAddRoles() {
		if (this.addRoles != null && !this.addRoles.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds an add role to the list of add roles.
	 * 
	 * @param aRole
	 *           Role to add to the list of add roles.
	 */
	public void addAddRole(EPPOrgRole aRole) {
		if (this.addRoles == null) {
			this.addRoles = new ArrayList<EPPOrgRole>();
		}
		this.addRoles.add(aRole);
	}

	/**
	 * Gets the add roles.
	 * 
	 * @return List of add roles set.
	 */
	public List<EPPOrgRole> getAddRoles() {
		return this.addRoles;
	}

	/**
	 * Sets the add roles.
	 * 
	 * @param aRoles
	 *           List of add roles
	 */
	public void setAddRoles(List<EPPOrgRole> aRoles) {
		this.addRoles = aRoles;
	}

	/**
	 * Is there any remove roles set?
	 * 
	 * @return <code>true</code> if there is at least one remove
	 *         {@link EPPOrgRole} set; <code>false</code> otherwise.
	 */
	public boolean hasRemRoles() {
		if (this.remRoles != null && !this.remRoles.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds a remove role to the list of remove roles.
	 * 
	 * @param aRole
	 *           Role to add to the list of remove roles.
	 */
	public void addRemRole(EPPOrgRole aRole) {
		if (this.remRoles == null) {
			this.remRoles = new ArrayList<EPPOrgRole>();
		}
		this.remRoles.add(aRole);
	}

	/**
	 * Gets the remove roles.
	 * 
	 * @return List of remove roles set.
	 */
	public List<EPPOrgRole> getRemRoles() {
		return this.remRoles;
	}

	/**
	 * Sets the remove roles.
	 * 
	 * @param aRoles
	 *           List of remove roles
	 */
	public void setRemRoles(List<EPPOrgRole> aRoles) {
		this.remRoles = aRoles;
	}

	/**
	 * Adds a status to the list of statuses.
	 * 
	 * @param aStatus
	 *           Status to add to the list of statuses.
	 */
	public void addStatus(EPPOrgStatus aStatus) {
		if (this.statuses == null) {
			this.statuses = new ArrayList<EPPOrgStatus>();
		}
		this.statuses.add(aStatus);
	}

	/**
	 * Gets the list of statuses
	 * 
	 * @return the statuses
	 */
	public List<EPPOrgStatus> getStatuses() {
		return this.statuses;
	}

	/**
	 * Sets the list of statuses
	 * 
	 * @param aStatus
	 *           the statuses to set
	 */
	public void setStatuses(List<EPPOrgStatus> aStatus) {
		this.statuses = aStatus;
	}

	/**
	 * Is there any add statuses set?
	 * 
	 * @return <code>true</code> if there is at least one add
	 *         {@link EPPOrgStatus} set; <code>false</code> otherwise.
	 */
	public boolean hasAddStatuses() {
		if (this.addStatuses != null && !this.addStatuses.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds an add status to the list of add statuses.
	 * 
	 * @param aStatus
	 *           Status to add to the list of add statuses.
	 */
	public void addAddStatus(EPPOrgStatus aStatus) {
		if (this.addStatuses == null) {
			this.addStatuses = new ArrayList<EPPOrgStatus>();
		}
		this.addStatuses.add(aStatus);
	}

	/**
	 * Gets the add statuses.
	 * 
	 * @return List of add statuses set.
	 */
	public List<EPPOrgStatus> getAddStatuses() {
		return this.addStatuses;
	}

	/**
	 * Sets the add statuses.
	 * 
	 * @param aStatuses
	 *           List of add statuses
	 */
	public void setAddStatuses(List<EPPOrgStatus> aStatuses) {
		this.addStatuses = aStatuses;
	}

	/**
	 * Is there any remove statuses set?
	 * 
	 * @return <code>true</code> if there is at least one remove
	 *         {@link EPPOrgStatus} set; <code>false</code> otherwise.
	 */
	public boolean hasRemStatuses() {
		if (this.remStatuses != null && !this.remStatuses.isEmpty()) {
			return true;
		}
		else {
			return false;
		}
	}

	/**
	 * Adds a remove status to the list of remove statuses.
	 * 
	 * @param aStatus
	 *           Status to add to the list of remove statuses.
	 */
	public void addRemStatus(EPPOrgStatus aStatus) {
		if (this.remStatuses == null) {
			this.remStatuses = new ArrayList<EPPOrgStatus>();
		}
		this.remStatuses.add(aStatus);
	}

	/**
	 * Gets the remove statuses.
	 * 
	 * @return List of remove statuses set.
	 */
	public List<EPPOrgStatus> getRemStatuses() {
		return this.remStatuses;
	}

	/**
	 * Sets the remove statuses.
	 * 
	 * @param aStatuses
	 *           List of remove statuses
	 */
	public void setRemStatuses(List<EPPOrgStatus> aStatuses) {
		this.remStatuses = aStatuses;
	}

	/**
	 * Sends a Org Check Command to the server.<br>
	 * <br>
	 * There required attributes that must be set prior to executing
	 * {@link #sendCheck()} include:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #addOrgId(String)} - Sets the org identifiers to check. At
	 * least one org identifier must be set.</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes can be set with the following:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #setTransId(String)} - Sets the client transaction identifier.
	 * </li>
	 * </ul>
	 * 
	 * @return {@link EPPOrgCheckResp} with the check results.
	 * 
	 * @throws EPPCommandException
	 *            On error
	 */
	public EPPOrgCheckResp sendCheck() throws EPPCommandException {
		if (this.orgIds == null || this.orgIds.isEmpty()) {
			throw new EPPCommandException("At least one org identifier is required for sendCheck()");
		}

		// Create the command
		EPPOrgCheckCmd theCommand = new EPPOrgCheckCmd(this.transId);
		theCommand.setOrgIds(this.orgIds);

		// Set command extension
		theCommand.setExtensions(this.extensions);

		// Reset Org attributes
		this.resetOrg();

		// process the command and response
		return (EPPOrgCheckResp) this.session.processDocument(theCommand, EPPOrgCheckResp.class);
	}

	/**
	 * Sends a Org Info Command to the server.<br>
	 * <br>
	 * There required attributes that must be set prior to executing
	 * {@link #sendInfo()} include:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #addOrgId(String)} - Sets the org identifier to get the
	 * information for. Only one org identifier is valid.</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes can be set with the following:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #setTransId(String)} - Sets the client transaction identifier.
	 * </li>
	 * </ul>
	 * 
	 * @return {@link EPPOrgInfoResp} that contains the org information.
	 * 
	 * @throws EPPCommandException
	 *            On error
	 */
	public EPPOrgInfoResp sendInfo() throws EPPCommandException {
		if (this.orgIds == null || this.orgIds.size() != 1) {
			throw new EPPCommandException("One org identifier is required for sendInfo()");
		}

		// Create the command
		EPPOrgInfoCmd theCommand = new EPPOrgInfoCmd(this.transId);
		theCommand.setOrgId(this.orgIds.get(0));

		// Set command extension
		theCommand.setExtensions(this.extensions);

		// Reset Org attributes
		this.resetOrg();

		// process the command and response
		return (EPPOrgInfoResp) this.session.processDocument(theCommand, EPPOrgInfoResp.class);
	}

	/**
	 * Sends a Org Create Command to the server.<br>
	 * <br>
	 * There required attributes that must be set prior to executing
	 * <code>sendCheck()</code> include:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #addOrgId(String)} - Sets the required org identifier to
	 * create.</li>
	 * <li>{@link #setRoles(List)} - Sets the list of org roles.</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes can be set with the following:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #setTransId(String)} - Sets the client transaction identifier.
	 * </li>
	 * <li>{@link #setContacts(List)} - Sets the org contacts.</li>
	 * <li>{@link #addStatus(EPPOrgStatus)} - Adds a status of the org. This is
	 * optional since the server will default to "ok".</li>
	 * <li>{@link #setParentId(String)} - Sets the parent org identifier of the
	 * org.</li>
	 * <li>{@link #addPostalInfo(EPPOrgPostalDefinition)} - Sets the postal
	 * information of the org.</li>
	 * <li>{@link #setEmail(String)} - Sets the org email.</li>
	 * <li>{@link #setVoice(String)} - Sets the org voice number.</li>
	 * <li>{@link #setVoiceExt(String)} - Sets the org voice number extension.
	 * </li>
	 * <li>{@link #setFax(String)} - Sets the org fax number.</li>
	 * <li>{@link #setFaxExt(String)} - Sets the org fax number extension.</li>
	 * <li>{@link #setUrl(String)} - Sets the org URL.</li>
	 * </ul>
	 * 
	 * @return {@link EPPOrgCreateResp} with the create result.
	 * 
	 * @throws EPPCommandException
	 *            On error
	 */
	public EPPOrgCreateResp sendCreate() throws EPPCommandException {
		if (this.orgIds == null || this.orgIds.isEmpty() || this.orgIds.size() != 1) {
			throw new EPPCommandException("A org identifier is required for sendCreate()");
		}
		if (this.roles == null || this.postalInfo.isEmpty()) {
			throw new EPPCommandException("A org role must be set");
		}

		// Create the command
		EPPOrgCreateCmd theCommand = new EPPOrgCreateCmd(this.transId);
		theCommand.setOrgId(this.orgIds.get(0));
		theCommand.setRoles(this.roles);
		theCommand.setStatuses(this.statuses);
		theCommand.setParentId(this.parentId);
		theCommand.setPostalInfo(this.postalInfo);
		theCommand.setVoice(this.voice);
		if (this.voice != null) {
			theCommand.setVoiceExt(this.voiceExt);
		}
		theCommand.setFax(this.fax);
		if (this.fax != null) {
			theCommand.setFaxExt(this.faxExt);
		}
		theCommand.setEmail(this.email);
		theCommand.setUrl(this.url);
		theCommand.setContacts(this.contacts);

		// Set command extension
		theCommand.setExtensions(this.extensions);

		// Reset Org attributes
		this.resetOrg();

		// process the command and response
		return (EPPOrgCreateResp) this.session.processDocument(theCommand, EPPOrgCreateResp.class);
	}

	/**
	 * Sends a Org Delete Command to the server.<br>
	 * <br>
	 * There required attributes that must be set prior to executing
	 * {@link #sendInfo()} include:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #addOrgId(String)} - Sets the org identifier to get deleted.
	 * Only one org identifier is valid.</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes can be set with the following:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #setTransId(String)} - Sets the client transaction identifier.
	 * </li>
	 * </ul>
	 * 
	 * @return {@link EPPResponse} that contains the deletion result.
	 * 
	 * @throws EPPCommandException
	 *            On error
	 */
	public EPPResponse sendDelete() throws EPPCommandException {
		if (this.orgIds == null || this.orgIds.size() != 1) {
			throw new EPPCommandException("One org identifier is required for sendDelete()");
		}

		// Create the command
		EPPOrgDeleteCmd theCommand = new EPPOrgDeleteCmd(this.transId);
		theCommand.setOrgId(this.orgIds.get(0));

		// Set command extension
		theCommand.setExtensions(this.extensions);

		// Reset Org attributes
		this.resetOrg();

		// process the command and response
		return (EPPResponse) this.session.processDocument(theCommand, EPPResponse.class);
	}

	/**
	 * Sends a Org Update Command to the server.<br>
	 * <br>
	 * There required attributes that must be set prior to executing
	 * <code>sendCheck()</code> include:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #addOrgId(String)} - Sets the org identifier to create.</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes can be set with the following:<br>
	 * <br>
	 * <ul>
	 * <li>{@link #setTransId(String)} - Sets the client transaction identifier.
	 * </li>
	 * <li>{@link #setParentId(String)} - Sets the parent org identifier of the
	 * org.</li>
	 * <li>{@link #addPostalInfo(EPPOrgPostalDefinition)} - Sets the postal
	 * information of the org.</li>
	 * <li>{@link #setVoice(String)} - Sets the org voice number.</li>
	 * <li>{@link #setVoiceExt(String)} - Sets the org voice number extension.
	 * </li>
	 * <li>{@link #setFax(String)} - Sets the org fax number.</li>
	 * <li>{@link #setFaxExt(String)} - Sets the org fax number extension.</li>
	 * <li>{@link #setEmail(String)} - Sets the org email.</li>
	 * <li>{@link #setUrl(String)} - Sets the org URL.</li>
	 * <li>{@link #setAddContacts(List)} - Sets the org contacts to add.</li>
	 * <li>{@link #setRemContacts(List)} - Sets the org contacts to remove.</li>
	 * <li>{@link #setAddRoles(List)} - Sets the org roles to add.</li>
	 * <li>{@link #setRemRoles(List)} - Sets the org roles to remove.</li>
	 * <li>{@link #setAddStatuses(List)} - Sets the org statuses to add.</li>
	 * <li>{@link #setRemStatuses(List)} - Sets the org statuses to remove.</li>
	 * </ul>
	 * 
	 * @return {@link EPPResponse} with the update result.
	 * 
	 * @throws EPPCommandException
	 *            On error
	 */
	public EPPResponse sendUpdate() throws EPPCommandException {
		if (this.orgIds == null || this.orgIds.isEmpty() || this.orgIds.size() != 1) {
			throw new EPPCommandException("A org identifier is required for sendCreate()");
		}

		// Create the command
		EPPOrgUpdateCmd theCommand = new EPPOrgUpdateCmd(this.transId);
		theCommand.setOrgId(this.orgIds.get(0));
		theCommand.setParentId(this.parentId);
		theCommand.setPostalInfo(this.postalInfo);
		theCommand.setVoice(this.voice);
		if (this.voice != null) {
			theCommand.setVoiceExt(this.voiceExt);
		}
		theCommand.setFax(this.fax);
		if (this.fax != null) {
			theCommand.setFaxExt(this.faxExt);
		}
		theCommand.setEmail(this.email);
		theCommand.setUrl(this.url);
		theCommand.setAddContacts(this.addContacts);
		theCommand.setRemContacts(this.remContacts);
		theCommand.setAddRoles(this.addRoles);
		theCommand.setRemRoles(this.remRoles);
		theCommand.setAddStatuses(this.addStatuses);
		theCommand.setRemStatuses(this.remStatuses);

		// Set command extension
		theCommand.setExtensions(this.extensions);

		// Reset Org attributes
		this.resetOrg();

		// process the command and response
		return (EPPResponse) this.session.processDocument(theCommand, EPPResponse.class);
	}

	/**
	 * Resets the Org instance to its initial state.
	 */
	protected void resetOrg() {
		this.transId = null;
		this.extensions = null;
		this.orgIds = null;
		this.parentId = null;
		this.postalInfo = null;
		this.voice = null;
		this.voiceExt = null;
		this.fax = null;
		this.faxExt = null;
		this.email = null;
		this.url = null;
		this.contacts = null;
		this.addContacts = null;
		this.remContacts = null;
		this.roles = null;
		this.addRoles = null;
		this.remRoles = null;
		this.statuses = null;
		this.addStatuses = null;
		this.remStatuses = null;
	}

	/**
	 * Gets the response associated with the last command. This method can be
	 * used to retrieve the server error response in the catch block of
	 * EPPCommandException.
	 *
	 * @return Response associated with the last command
	 */
	public EPPResponse getResponse() {
		return this.session.getResponse();
	}

}
