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

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.verisign.epp.codec.allocationtoken.EPPAllocationToken;
import com.verisign.epp.codec.domain.EPPDomainCreateResp;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.idnext.EPPIdnLangTag;
import com.verisign.epp.codec.idnmap.EPPIdnMap;
import com.verisign.epp.codec.namestoreext.EPPNamestoreExtNamestoreExt;
import com.verisign.epp.codec.orgext.EPPOrgExtCreate;
import com.verisign.epp.codec.orgext.EPPOrgExtId;
import com.verisign.epp.codec.orgext.EPPOrgExtUpdate;
import com.verisign.epp.codec.rgpext.EPPRgpExtReport;
import com.verisign.epp.codec.rgpext.EPPRgpExtRestore;
import com.verisign.epp.codec.rgpext.EPPRgpExtUpdate;
import com.verisign.epp.codec.syncext.EPPSyncExtUpdate;
import com.verisign.epp.codec.whois.EPPWhoisInf;
import com.verisign.epp.interfaces.EPPCommandException;
import com.verisign.epp.interfaces.EPPDomain;
import com.verisign.epp.interfaces.EPPRelatedDomain;
import com.verisign.epp.interfaces.EPPSession;

/**
 * NameStore Domain interface that extends that standard <code>EPPDomain</code>
 * by adding new operations like restore request, restore report, and sync.
 */
public class NSDomain extends EPPRelatedDomain {

	/**
	 * Restore report information
	 */
	private EPPRgpExtReport report = null;

	/**
	 * Month for sync command
	 */
	private int month = -1;

	/**
	 * Day for sync command
	 */
	private int day = -1;

	/**
	 * Org extension create
	 */
	private EPPOrgExtCreate orgCreate = null;

	/**
	 * Org extension update
	 */
	private EPPOrgExtUpdate orgUpdate = null;

	/**
	 * Constant used to remove all DS using <code>aRemDsData</code> parameter of
	 * the method {@link #setSecDNSUpdate(List, List)}.
	 */
	public static final List REM_ALL_DS = new ArrayList();

	/**
	 * Creates an <code>NSDomain</code> with an established
	 * <code>EPPSession</code>.
	 * 
	 * @param aSession
	 *           Established session
	 */
	public NSDomain(EPPSession aSession) {
		super(aSession);
	}

	/**
	 * Send a restore request.<br>
	 * <br>
	 * The required attributes have been set with the following methods:<br>
	 * <br>
	 * <ul>
	 * <li><code>addDomainName</code> - Sets the domain name to restore. Only one
	 * domain name is valid.</li>
	 * <li><code>setSubProductID</code> - Sets the sub-product id</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes have been set with the following:<br>
	 * <br>
	 * <ul>
	 * <li><code>setTransId</code> - Sets the client transaction identifier</li>
	 * </ul>
	 * 
	 * @return <code>EPPResponse</code> containing the Domain restore request
	 *         result.
	 *
	 * @exception EPPCommandException
	 *               Error executing the restore request command. Use
	 *               <code>getResponse</code> to get the associated server error
	 *               response.
	 */
	public EPPResponse sendRestoreRequest() throws EPPCommandException {
		super.addExtension(new EPPRgpExtUpdate(new EPPRgpExtRestore()));
		return super.sendUpdate();
	}

	/**
	 * Send a restore report.<br>
	 * <br>
	 * The required attributes have been set with the following methods:<br>
	 * <br>
	 * <ul>
	 * <li><code>addDomainName</code> - Sets the domain name for report. Only one
	 * domain name is valid.</li>
	 * <li><code>setSubProductID</code> - Sets the sub-product id</li>
	 * <li><code>setReport</code> - Sets the report information</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes have been set with the following:<br>
	 * <br>
	 * <ul>
	 * <li><code>setTransId</code> - Sets the client transaction identifier</li>
	 * </ul>
	 * 
	 * @return <code>EPPResponse</code> containing the Domain restore report
	 *         result.
	 *
	 * @exception EPPCommandException
	 *               Error executing the restore report command. Use
	 *               <code>getResponse</code> to get the associated server error
	 *               response.
	 */
	public EPPResponse sendRestoreReport() throws EPPCommandException {
		if (this.report == null) {
			throw new EPPCommandException("Report is required for sendRestoreReport()");
		}
		super.addExtension(new EPPRgpExtUpdate(new EPPRgpExtRestore(this.report)));
		return super.sendUpdate();
	}

	/**
	 * Send a sync command for a domain with a specified expiration month and day
	 * <br>
	 * <br>
	 * The required attributes have been set with the following methods:<br>
	 * <br>
	 * <ul>
	 * <li><code>addDomainName</code> - Sets the domain name for report. Only one
	 * domain name is valid.</li>
	 * <li><code>setSubProductID</code> - Sets the sub-product id</li>
	 * <li><code>setMonth</code> - Month to set expiration date</li>
	 * <li><code>setDay</code> - Day to set expiration date</li>
	 * </ul>
	 * <br>
	 * <br>
	 * The optional attributes have been set with the following:<br>
	 * <br>
	 * <ul>
	 * <li><code>setTransId</code> - Sets the client transaction identifier</li>
	 * </ul>
	 * 
	 * @return <code>EPPResponse</code> containing the Domain sync result.
	 *
	 * @exception EPPCommandException
	 *               Error executing the sync command. Use
	 *               <code>getResponse</code> to get the associated server error
	 *               response.
	 */
	public EPPResponse sendSync() throws EPPCommandException {
		if (this.month < Calendar.JANUARY || this.month > Calendar.DECEMBER) {
			throw new EPPCommandException("Month " + this.month + " is invalid value for sendRestoreReport()");
		}

		if (this.day < 1 || this.day > 31) {
			throw new EPPCommandException("Day " + this.day + " is invalid value for sendRestoreReport()");
		}

		super.addExtension(new EPPSyncExtUpdate(this.month, this.day));
		return super.sendUpdate();
	}
	
	
	/**
	 * Sends a Domain Name Create Command to the server.<br>
	 * <br>
	 * The required attributes have been set with the following
	 * methods:<br><br>
	 * 
	 * <ul>
	 * <li>
	 * <code>addDomainName</code> - Sets the domain name to create.  Only one
	 * domain name is valid.
	 * </li>
	 * <li>
	 * <code>setAuthString</code> - Sets the domain name authorization string.
	 * </li>
	 * </ul>
	 * 
	 * <br><br>
	 * The optional attributes have been set with the following:<br><br>
	 * 
	 * <ul>
	 * <li>
	 * <code>setTransId</code> - Sets the client transaction identifier
	 * </li>
	 * <li>
	 * <code>setPeriodLength</code> - Sets the registration period (default =
	 * 1)
	 * </li>
	 * <li>
	 * <code>setPeriodUnit</code> - Sets the registration period unit (default
	 * = <code>PERIOD_YEAR</code>)
	 * </li>
	 * <li>
	 * <code>setRegistrant</code> - Sets the Registrant for the domain.  This
	 * is required for thick registries.
	 * </li>
	 * <li>
	 * <code>addContact</code> - Add domain contact
	 * </li>
	 * <li>
	 * <code>addHostName</code> - Add domain delegation host
	 * </li>
	 * <li>
	 * <code>addOrgId</code> - Add an organization identifier with a role 
	 * </li>
	 * </ul>
	 * 
	 *
	 * @return <code>EPPDomainCreateResp</code> containing the Domain create
	 * 		   result.
	 *
	 * @exception EPPCommandException Error executing the create command.  Use
	 * 			  <code>getResponse</code> to get the associated server error
	 * 			  response.
	 */
	@Override
	public EPPDomainCreateResp sendCreate() throws EPPCommandException {
		if (this.orgCreate != null) {
			super.addExtension(this.orgCreate);
		}
		
		return super.sendCreate();
	}
	
	/**
	 * Sends a Domain Name Update Command to the server.<br>
	 * <br>
	 * The required attributes have been set with the following
	 * methods:<br><br>
	 * 
	 * <ul>
	 * <li>
	 * <code>addDomainName</code> - Sets the domain name to update.  Only one
	 * domain name is valid.
	 * </li>
	 * </ul>
	 * 
	 * <br><br>
	 * The optional attributes have been set with the following:<br><br>
	 * 
	 * <ul>
	 * <li>
	 * <code>setTransId</code> - Sets the client transaction identifier
	 * </li>
	 * <li>
	 * <code>setUpdateAttrib(int,String,int)</code> - Adds/removes hosts
	 * </li>
	 * <li>
	 * <code>setUpdateAttrib(int,DomainStatus,int)</code> - Adds/removes
	 * statuses
	 * </li>
	 * <li>
	 * <code>setUpdateAttrib(int,String,String,int)</code> - Adds/removes
	 * contacts
	 * </li>
	 * <li>
	 * <code>setRegistrant</code> - Sets the Registrant for the domain.
	 * </li>
	 * <li>
	 * <code>setAuthString</code> - Sets the domain name authorization string.
	 * </li>
	 * <li>
	 * <code>addUpdateOrgId</code> - Add an update to organization identifier 
	 * </li>
	 * </ul>
	 * 
	 * At least one update attribute needs to be set.
	 *
	 * @return <code>EPPResponse</code> containing the Domain update result.
	 *
	 * @exception EPPCommandException Error executing the update command.  Use
	 * 			  <code>getResponse</code> to get the associated server error
	 * 			  response.
	 */
	@Override
	public EPPResponse sendUpdate() throws EPPCommandException {
		if (this.orgUpdate != null) {
			super.addExtension(this.orgUpdate);
		}
		
		return super.sendUpdate();
	}
	

	/**
	 * Gets the day of sync.
	 * 
	 * @return Returns the day of sync if set; <code>-1</code> otherwise
	 */
	public int getDay() {
		return this.day;
	}

	/**
	 * Sets the day of sync.
	 * 
	 * @param aDay
	 *           The day to set.
	 */
	public void setDay(int aDay) {
		this.day = aDay;
	}

	/**
	 * Gets the month of sync.
	 * 
	 * @return the month using a <code>java.util.Calendar</code> month constant
	 *         if defined; <code>-1</code> otherwise
	 */
	public int getMonth() {
		return this.month;
	}

	/**
	 * Sets the month of sync.
	 * 
	 * @param aMonth
	 *           the month using a <code>java.util.Calendar</code> month constant
	 */
	public void setMonth(int aMonth) {
		this.month = aMonth;
	}

	/**
	 * Gets the report information for the restore report.
	 * 
	 * @return Returns the report if defined; <code>null</code> otherwise.
	 */
	public EPPRgpExtReport getReport() {
		return this.report;
	}

	/**
	 * Sets the report information for the restore report.
	 * 
	 * @param aReport
	 *           Report information
	 */
	public void setReport(EPPRgpExtReport aReport) {
		this.report = aReport;
	}

	/**
	 * Set the IDN language tag used with <code>sendCreate</code>.
	 * 
	 * @param aLangTag
	 *           Valid XML schema language value as defined by
	 *           &lt;a href="http://www.w3.org/TR/xmlschema-2/#language"/&gt;. For
	 *           example, use a two letter language tag like <code>en</code> or
	 *           <code>fr</code>.
	 */
	public void setIDNLangTag(String aLangTag) {
		super.addExtension(new EPPIdnLangTag(aLangTag));
	}

	/**
	 * Set the IDN Map used with <code>sendCreate</code>, which includes the IDN
	 * table identifer and optionally the uname.
	 * 
	 * @param aTable
	 *           IDN table identifier
	 * @param aUname
	 *           OPTIONAL domain name in Unicode NFC. Set to <code>null</code> if
	 *           undefined.
	 */
	public void setIDNMap(String aTable, String aUname) {
		super.addExtension(new EPPIdnMap(aTable, aUname));
	}

	/**
	 * Sets the domain sub-product id which specifies which is the target
	 * registry for the domain operation. Some possible values include CC, TV,
	 * COM, NET. This results in a <code>EPPNamestoreExtNamestoreExt</code>
	 * extension being added to the command.
	 * 
	 * @param aSubProductID
	 *           Sub-product id of domain operation. Some constants for the
	 *           sub-product id are defined in <code>NSSubProduct</code>. Passing
	 *           <code>null</code> will not add any extension.
	 */
	public void setSubProductID(String aSubProductID) {
		if (aSubProductID != null) {
			super.addExtension(new EPPNamestoreExtNamestoreExt(aSubProductID));
		}
	}

	/**
	 * Sets if whois information is desired in the response to a call to
	 * <code>sendInfo()</code>. If <code>true</code> is specified, the
	 * <code>com.verisign.epp.codec.whois.EPPWhoisInfData</code> extension will
	 * be added to the
	 * <code>com.verisign.epp.codec.domain.EPPDomainInfoResp</code> when the
	 * server supports it.
	 * 
	 * @param aWhoisInfo
	 *           <code>true</code> to include the whois response information;
	 *           <code>false</code> otherwise.
	 */
	public void setWhoisInfo(boolean aWhoisInfo) {
		super.addExtension(new EPPWhoisInf(aWhoisInfo));
	}

	/**
	 * Sets the list of <code>EPPSecDNSExtDsData</code> instances to add along
	 * with the list of <code>EPPSecDNSExtDsData</code> instances to remove. This
	 * method only supports secDNS-1.1. This method can be used to remove all DS
	 * data by passing the {@link #REM_ALL_DS} constant with the
	 * <code>aRemDsData</code> parameter, and can be used to replace all DS data
	 * by passing the {@link #REM_ALL_DS} constant with the
	 * <code>aRemDsData</code> parameter and setting the <code>aAddDsData</code>
	 * to a non-null, non-empty list.
	 * 
	 * @param aAddDsData
	 *           - List of
	 *           {@link com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData}
	 *           instances to add; <code>null</code> if there is nothing to add.
	 * @param aRemDsData
	 *           - List of
	 *           {@link com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData}
	 *           instances to remove; <code>null</code> if there is nothing to
	 *           remove. Set to {@link #REM_ALL_DS} constant to remove all DS
	 *           data.
	 * @exception EPPCommandException
	 *               Error with parameters passed in.
	 */
	public void setSecDNSUpdate(List aAddDsData, List aRemDsData) throws EPPCommandException {

		// Validate aAddDsData is secDNS-1.1
		if (aAddDsData != null && !aAddDsData.isEmpty()) {
			if (!(aAddDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData)) {
				throw new EPPCommandException("NSDomain.setSecDNSUpdate: Invalid aAddDsData element of type = "
				      + aAddDsData.get(0).getClass().getName());
			}
		}

		// Validate aRemDsData is secDNS-1.1
		if (aRemDsData != REM_ALL_DS && aRemDsData != null && !aRemDsData.isEmpty()) {
			if (!(aRemDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData)) {
				throw new EPPCommandException("NSDomain.setSecDNSUpdate: Invalid aRemDsData element of type = "
				      + aRemDsData.get(0).getClass().getName());
			}
		}

		com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate theExt = new com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate();
		theExt.setAddDsData(aAddDsData);

		if (aRemDsData == REM_ALL_DS) {
			theExt.setRemAllData(true);
		}
		else {
			theExt.setRemDsData(aRemDsData);
		}

		super.addExtension(theExt);
	}

	/**
	 * Sets the list of <code>EPPSecDNSExtDsData</code> instances in order to
	 * create delegation signer (DS) information.
	 * 
	 * @param aDsData
	 *           - List of <code>EPPSecDNSExtDsData</code> instances
	 */
	public void setSecDNSCreate(List aDsData) {

		// aDsData has elements?
		if (aDsData != null && !aDsData.isEmpty()) {

			// secDNS-1.0?
			if (aDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtDsData) {
				super.addExtension(new com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtCreate(aDsData));
			} // secDNS-1.1?
			else if (aDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData) {
				com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtCreate theExt = new com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtCreate();
				theExt.setDsData(aDsData);
				super.addExtension(theExt);
			}

		}

	}

	/**
	 * Sets the list of <code>EPPCoaExtAttr</code> instances to associate Client
	 * Object Attributes with the object being created.
	 * 
	 * @param aAttrs
	 *           - List of <code>EPPCoaExtAttr</code> instances
	 */
	public void setCoaCreate(List aAttrs) {
		if (aAttrs != null && !aAttrs.isEmpty()) {
			super.addExtension(new com.verisign.epp.codec.coaext.EPPCoaExtCreate(aAttrs));
		}
	}

	/**
	 * Sets the list of <code>EPPCoaExtAttr</code> instances to associate Client
	 * Object Attributes with the object being updated.
	 * 
	 * @param aAttrs
	 *           - List of <code>EPPCoaExtAttr</code> instances
	 */
	public void setCoaUpdateForPut(List aAttrs) {
		if (aAttrs != null && !aAttrs.isEmpty()) {
			com.verisign.epp.codec.coaext.EPPCoaExtUpdate update = new com.verisign.epp.codec.coaext.EPPCoaExtUpdate();
			update.setPutAttrs(aAttrs);
			super.addExtension(update);
		}
	}

	/**
	 * Sets the list of <code>EPPCoaExtKey</code> instances to specify Client
	 * Object Attributes to be removed from the object being updated.
	 * 
	 * @param aKeys
	 *           - List of <code>EPPCoaExtKey</code> instances
	 */
	public void setCoaUpdateForRem(List aKeys) {
		if (aKeys != null && !aKeys.isEmpty()) {
			com.verisign.epp.codec.coaext.EPPCoaExtUpdate update = new com.verisign.epp.codec.coaext.EPPCoaExtUpdate();
			update.setRemAttrs(aKeys);
			super.addExtension(update);
		}
	}

	/**
	 * Sets the list of <code>EPPSecDNSExtDsData</code> instances in order to add
	 * delegation signer (DS) information.
	 * 
	 * @param aAddDsData
	 *           - List of <code>EPPSecDNSExtDsData</code> instances
	 * @param aUrgent
	 *           - boolean value indicates whether it is a high priority request
	 * @deprecated Supports secDNS-1.0 and secDNS-1.1, but use the secDNS-1.1
	 *             method {@link #setSecDNSUpdate(List, List)}.
	 */
	@Deprecated
	public void setSecDNSUpdateForAdd(List aAddDsData, boolean aUrgent) {

		// aDsData has elements?
		if (aAddDsData != null && !aAddDsData.isEmpty()) {

			// secDNS-1.0?
			if (aAddDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtDsData) {
				com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate theExt = new com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate();
				theExt.setAdd(aAddDsData);
				theExt.setUrgent(aUrgent);
				super.addExtension(theExt);
			} // secDNS-1.1?
			else if (aAddDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData) {
				com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate theExt = new com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate();
				theExt.setAddDsData(aAddDsData);
				theExt.setUrgent(aUrgent);
				super.addExtension(theExt);
			}

		}

	}

	/**
	 * Sets the list of <code>EPPSecDNSExtDsData</code> instances in order to
	 * change delegation signer (DS) information. This method is only used for
	 * secDNS-1.0.
	 * 
	 * @param aChgDsData
	 *           - List of
	 *           {@link com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtDsData}
	 *           instances
	 * @param aUrgent
	 *           - boolean value indicates whether it is a high priority request
	 * @deprecated Only supported with secDNS-1.0. Look to use the secDNS-1.1
	 *             method {@link #setSecDNSUpdate(List, List)}.
	 */
	@Deprecated
	public void setSecDNSUpdateForChg(List aChgDsData, boolean aUrgent) {

		// Does list contain secDNS-1.0 EPPSecDNSExtDsData?
		if (aChgDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtDsData) {
			com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate updateExt = new com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate(
			      null, aChgDsData, null);
			updateExt.setUrgent(aUrgent);
			super.addExtension(updateExt);
		}

	}

	/**
	 * Sets the list of <code>Integer</code> instances in order to remove
	 * delegation signer (DS) information.
	 * 
	 * @param aRemDsData
	 *           - List of <code>Integer</code> instances for secDNS-1.0 or
	 *           {@link com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtDsData}
	 *           instances for secDNS-1.1.
	 * @param aUrgent
	 *           - boolean value indicates whether it is a high priority request
	 * @deprecated Supports secDNS-1.0 and secDNS-1.1, but use the secDNS-1.1
	 *             method {@link #setSecDNSUpdate(List, List)}.
	 */
	@Deprecated
	public void setSecDNSUpdateForRem(List aRemDsData, boolean aUrgent) {

		// aDsData has elements?
		if (aRemDsData != null && !aRemDsData.isEmpty()) {

			// secDNS-1.0?
			if (aRemDsData.get(0) instanceof Integer) {
				com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate theExt = new com.verisign.epp.codec.secdnsext.v10.EPPSecDNSExtUpdate();
				theExt.setRem(aRemDsData);
				theExt.setUrgent(aUrgent);
				super.addExtension(theExt);
			} // secDNS-1.1?
			else if (aRemDsData.get(0) instanceof com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData) {
				com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate theExt = new com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtUpdate();
				theExt.setRemDsData(aRemDsData);
				theExt.setUrgent(aUrgent);
				super.addExtension(theExt);
			}

		}

	}

	/**
	 * Sets the allocation token extension with the token value to be passed
	 * along with either <code>sendCheck</code>, <code>sendCreate()</code>,
	 * <code>sendUpdate</code>, or <code>sendTransfer</code>. The allocation
	 * token is used to allocation a domain name that be held or reserved for
	 * use.
	 * 
	 * @param aAllocationToken
	 *           Allocation token value
	 */
	public void setAllocationToken(String aAllocationToken) {
		super.addExtension(new EPPAllocationToken(aAllocationToken));
	}

	/**
	 * Adds an org identifier for use with {@link #sendCreate()}.
	 * 
	 * @param aOrgId
	 *           Org identifier with role to add
	 */
	public void addOrgId(EPPOrgExtId aOrgId) {
		if (this.orgCreate == null) {
			this.orgCreate = new EPPOrgExtCreate();
		}
		this.orgCreate.addOrgId(aOrgId);
	}

	/**
	 * Updates the org identifier used with {@link #sendUpdate()}. There are
	 * three possible actions that can be used including
	 * <code>EPPDomain.ADD</code>, <code>EPPDomain.REMOVE</code>, and
	 * <code>EPPDomain.CHANGE</code> for the org identifier.
	 * 
	 * @param aAction
	 *           One of the <code>EPPDomain.ADD</code>,
	 *           <code>EPPDomain.REMOVE</code>, and <code>EPPDomain.CHANGE</code>
	 *           for the org identifier.
	 * @param aOrgId
	 *           Org identifier to add, remove, or change
	 */
	public void addUpdateOrgId(int aAction, EPPOrgExtId aOrgId) {
		
		if (this.orgUpdate == null) {
			this.orgUpdate = new EPPOrgExtUpdate();
		}
		switch (aAction) {
			case EPPDomain.ADD:
				this.orgUpdate.addAddOrg(aOrgId);
				break;
			case EPPDomain.REMOVE:
				this.orgUpdate.addRemOrg(aOrgId);
				break;
			case EPPDomain.CHANGE:
				this.orgUpdate.addChgOrg(aOrgId);
				break;
			default:
				throw new InvalidParameterException("NSDomain.updateOrgId(int, EPPOrgExtId): Invalid action " + aAction);
		}
	}

	/**
	 * Resets the domain attributes for the next command.
	 */
	protected void resetDomain() {
		super.resetDomain();
		this.day = -1;
		this.month = -1;
		this.report = null;
		this.orgCreate = null;
		this.orgUpdate = null;
	}

} // End class NSDomain
