/*******************************************************************************
 *  Copyright 2017-2018 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package cdac.medinfo.sdk.dcm30_04.dicommodel.modules;



import cdac.medinfo.sdk.dcm30_04.baselibs.BreedRegistrationSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.DeidentificationMethodCodeSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.IssuerofPatientIDMacro;
import cdac.medinfo.sdk.dcm30_04.baselibs.OtherPatientIDsSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.PatientBreedCodeSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.PatientSpeciesCodeSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedPatientPhotoSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedPatientSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPatientIdentityRemoved;
import cdac.medinfo.sdk.dcm30_04.enums.EnumQualityControlSubject;
import cdac.medinfo.sdk.dcm30_04.enums.EnumResponsiblePersonRole;

import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ItemLimitException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ValidationException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

/**
 * This class specifies the Attributes of the Patient that describe and identify the Patient who is
 * the subject of a diagnostic Study. This Module contains Attributes of the patient that are needed
 * for diagnostic interpretation of the Image and are common for all studies performed on the
 * patient.
 */
public class PatientModule extends Module  
{
	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;

 	/**
	 * The obj Issuer of Patient ID Macro.
	 */
	IssuerofPatientIDMacro objIssuerofPatientIDMacro = null;

	/**
	 * Instantiates a new patient module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public PatientModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0008,0x1120));
		objSingleCollection.add(new Tag(0x0010,0x0010));
		objSingleCollection.add(new Tag(0x0010,0x0020));
		objSingleCollection.add(new Tag(0x0010,0x0021));
		objSingleCollection.add(new Tag(0x0010,0x0030));
		objSingleCollection.add(new Tag(0x0010,0x0032));
		objSingleCollection.add(new Tag(0x0010,0x0040));
		objSingleCollection.add(new Tag(0x0010,0x1000));
		objSingleCollection.add(new Tag(0x0010,0x1001));
		objSingleCollection.add(new Tag(0x0010,0x2160));
		objSingleCollection.add(new Tag(0x0010,0x4000));
		objSingleCollection.add(new Tag(0x0010,0x1100));
		objSingleCollection.add(new Tag(0x0010,0x0200));
		objSingleCollection.add(new Tag(0x0010,0x1002));
		objSingleCollection.add(new Tag(0x0010,0x2201));
		objSingleCollection.add(new Tag(0x0010,0x2202));
		objSingleCollection.add(new Tag(0x0010,0x2292));
		objSingleCollection.add(new Tag(0x0010,0x2293));
		objSingleCollection.add(new Tag(0x0010,0x2294));
		objSingleCollection.add(new Tag(0x0010,0x2297));
		objSingleCollection.add(new Tag(0x0010,0x2298));
		objSingleCollection.add(new Tag(0x0010,0x2299));
		objSingleCollection.add(new Tag(0x0012,0x0062));
		objSingleCollection.add(new Tag(0x0012,0x0063));
		objSingleCollection.add(new Tag(0x0012,0x0064));
	}

	/**
	 * Validates each Attribute in the Module according to the Type
	 * of the Attribute.Attributes are of 5 types.
	 * Type 1,Type 2 are Mandatory:
	 * Mandatory Attributes have to present in the Module.
	 * Type 1C,2C are Conditional:
	 * Conditional Attributes' presence depend on a condition.
	 * If the condition is satisfied the Attribute has to be present.
	 * Type 3 are Optional
	 * Optional Attributes can be added as and when required.
	 * 
	 * @return Boolean - status indicating success or failure
	 * 
	 * @throws InvalidModuleException - If validation of Module fails
	 */
	public  boolean validateModule() throws InvalidModuleException
	{

		try
		{			//Valdiate mandatory attributes
			if(!isPresent(0x0010,0x0010))
				throw new MandatoryMissingException("0010,0010");
			if(!isPresent(0x0010,0x0020))
				throw new MandatoryMissingException("0010,0020");
			if(!isPresent(0x0010,0x0030))
				throw new MandatoryMissingException("0010,0030");
			if(!isPresent(0x0010,0x0040))
				throw new MandatoryMissingException("0010,0040");

			//Validate Conditional,Optional Sequence attributes
			//Validation for Sequence
			if(isPresent(0x0008,0x1120))
			{
				ReferencedPatientSequence objReferencedPatientSequence = getReferencedPatientSequence();
				int iNoOfItems = objReferencedPatientSequence.noOfItems();
				if(iNoOfItems > 1)
					throw new ItemLimitException("0008,1120 shall contain Single Item");
				objReferencedPatientSequence.validateForModule();
			}
			
			if(isPresent(0x0010,0x2297))
				if(!isPresent(0x0010,0x2298))
					throw new ConditionFailedException("0x0010,0x2298");

			if(isPresent(0x0012,0x0062) && getValue(0x0012,0x0062).equals(EnumPatientIdentityRemoved.YES) && !isPresent(0x0012,0x0064))
				if(!isPresent(0x0012,0x0063))
					throw new ConditionFailedException("0x0012,0x0063");
		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

			
				throw new InvalidModuleException(this.getClass().getSimpleName(),mme);

		}
		catch(ConditionFailedException ce)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(ce.getMessage());
			}
			throw new ValidationException(this.getClass().getSimpleName(),ce); 
		}
		catch(ItemLimitException ile)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(ile.getMessage());

			
				throw new InvalidModuleException(this.getClass().getSimpleName(),ile);

		}
		catch(ValidationException ve)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(ve.getMessage());

			
				throw new InvalidModuleException(this.getClass().getSimpleName(),ve);

		}
		return true;
	}

	/**
	 * Sets the Patient Name in Patient Module.
	 * 
	 * @param strPatientName - Patient's full name.
	 */
	public void setPatientName(String strPatientName)
	{
		/* Accept the Patient Name in String format of type PN.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0010, 0x0010, DicomConstants.DCM_DT_PN, strPatientName);
	}

	/**
	 * Sets the strPatient ID in Patient Module.
	 * 
	 * @param strPatientID - Primary hospital identification number or
	 * code for the patient.
	 */	
	public void setPatientID(String strPatientID)
	{
		/*Accept Image identification characteristics in String Array format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010,0x0020, DicomConstants.DCM_DT_LO, strPatientID);
	}

	/**
	 * Sets the Issuer Of Patient ID in Patient Module.
	 * 
	 * @param strIssuerOfPatientID - String value of Identifier of the Assigning Authority that
	 * issued the Patient ID.
	 */	
	public void setIssuerOfPatientID(String strIssuerOfPatientID)
	{
		/*Accept Image identification characteristics in String Array format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010,0x0021, DicomConstants.DCM_DT_LO, strIssuerOfPatientID);
	}

	/**
	 * Sets the Patient Birth Date in Patient Module.
	 * 
	 * @param strPatientBirthDate : String value of Birth date of the patient.
	 */	
	public void setPatientBirthDate(String strPatientBirthDate)
	{
		/* Accept the Patient BirthDate value in String format of type DA.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x0030, DicomConstants.DCM_DT_DA, strPatientBirthDate);
	}

	/**
	 * Sets the Patient Sex in Patient Module.
	 * 
	 * @param strPatientSex : String value of Sex of the patient.
	 */	
	public void setPatientSex(String strPatientSex)
	{
		/* Accept the Patient Sex value in String format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x0040, DicomConstants.DCM_DT_CS, strPatientSex);
	}	

	/**
	 * Sets Quality Control Subject.
	 * 
	 * @param enumQualityControlSubject - enum value of Quality Control Subject.
	 */
	public void setQualityControlSubject(EnumQualityControlSubject enumQualityControlSubject)
	{
		/* Accept the Quality Control Subject value in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x0200, DicomConstants.DCM_DT_CS, enumQualityControlSubject);
	}
	
	/**
	 * Sets the Patient Birth Time in Patient Module.
	 * 
	 * @param strPatientBirthTime :	String value of Birth time of the Patient..
	 */	
	public void setPatientBirthTime(String strPatientBirthTime)
	{
		/* Accept the Patient Birth Time value in String format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x0032, DicomConstants.DCM_DT_TM, strPatientBirthTime);
	}

	/**
	 * Sets the Other Patient IDs in Patient Module.
	 * 
	 * @param arrStrOtherPatientIDs :	String value of Other identification numbers or codes
	 * used to identify the patient
	 */	
	public void setOtherPatientIDs(String[] arrStrOtherPatientIDs)
	{
		/*Accept the Other Patient IDs value in String Array format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * 
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x1000, DicomConstants.DCM_DT_LO, arrStrOtherPatientIDs);
	}

	/**
	 * Sets the Other Patient Names in Patient Module.
	 * 
	 * @param arrStrOtherPatientNames :	String array of Other names used to identify the patient.
	 */	
	public void setOtherPatientNames(String[] arrStrOtherPatientNames)
	{
		/*Accept the Other Patient Names value in String Array format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * 
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x1001, DicomConstants.DCM_DT_PN, arrStrOtherPatientNames);
	}

	/**
	 * Sets the Ethnic Group in Patient Module.
	 * 
	 * @param strEthnicGroup the str ethnic group
	 */	
	public void setEthnicGroup(String strEthnicGroup)
	{
		/*Accept the Ethnic group value in String format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * 
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x2160, DicomConstants.DCM_DT_SH, strEthnicGroup);
	}	

	/**
	 * Sets the Patient Comments in Patient Module.
	 * 
	 * @param strPatientComments -	String value of User-defined additional information about
	 * the patient.
	 */	
	public void setPatientComments(String strPatientComments)
	{
		/*Accept the Patient Comments value in String format of type CS.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * 
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x4000, DicomConstants.DCM_DT_LT, strPatientComments);
	}	
	
	/**
	 * The species of the patient.
	 * @param strPatientSpeciesDescription - String value of Patient Species Description.
	 */
	public void setPatientSpeciesDescription(String strPatientSpeciesDescription)
	{
		/*Accept Patient Species Description in String format of type LO.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0010, 0x2201, DicomConstants.DCM_DT_LO, strPatientSpeciesDescription);
	}
	
	/**
	 * The breed of the patient.
	 * @param strPatientBreedDescription - String value of Patient Breed Description.
	 */
	public void setPatientBreedDescription(String strPatientBreedDescription)
	{
		/*Accept Patient Breed Description in String format of type LO.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0010, 0x2292, DicomConstants.DCM_DT_LO, strPatientBreedDescription);
	}
	
	/**
	 * Name of person with medical decision making authority for the patient.
	 * @param strResponsiblePerson - String value of Responsible Person.
	 */
	public void setResponsiblePerson(String strResponsiblePerson)
	{
		/*Accept Responsible Person in String format of type PN.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0010, 0x2297, DicomConstants.DCM_DT_PN, strResponsiblePerson);
	}
	
	/**
	 * Sets Responsible Person Role.
	 * 
	 * @param enumResponsiblePersonRole - enum value of Responsible Person Role.
	 */
	public void setResponsiblePersonRole(EnumResponsiblePersonRole enumResponsiblePersonRole)
	{
		/* Accept the Responsible Person Role value in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0010, 0x2298, DicomConstants.DCM_DT_CS, enumResponsiblePersonRole);
	}
	
	/**
	 * Name of organization with medical decision making authority for the patient.
	 * @param strResponsibleOrganization - String value of Responsible Organization.
	 */
	public void setResponsibleOrganization(String strResponsibleOrganization)
	{
		/*Accept Responsible Organization in String format of type LO.
		 * Read the Transfer Syntax and check to create ImplicitDE or ExplicitDE .
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0010, 0x2299, DicomConstants.DCM_DT_LO, strResponsibleOrganization);
	}
	
	/**
	 * Sets Patient Identity Removed.
	 * The true identity of the patient has been removed from the Attributes and the Pixel Data
	 * Enumerated Values:
	 * 1) YES
	 * 2) NO
	 * 
	 * @param enumPatientIdentityRemoved the enum Patient Identity Removed
	 */
	public void setPatientIdentityRemoved(EnumPatientIdentityRemoved  enumPatientIdentityRemoved)
	{
		/* Accept Patient Identity Removed in String format of type DS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Data Set
		 */
		addDataElement(0x0012, 0x0062, DicomConstants.DCM_DT_CS, enumPatientIdentityRemoved.getValue());
	}
	
	/**
	 * Sets Deidentification Method.
	 * 
	 * @param strDeidentificationMethod String value of Deidentification Method.
	 */
	public void setDeidentificationMethod(String strDeidentificationMethod)
	{
		/* Accept Deidentification Method format of type LO.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0012, 0x0063, DicomConstants.DCM_DT_LO, strDeidentificationMethod);
	}

	/**
	 * Return the String value of the attribute Patient Name.
	 * 
	 * @return String - returns the patient name
	 */
	public String getPatientName()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0010);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Return the String value of the attribute Patient ID.
	 * 
	 * @return String - returns the patient ID
	 */
	public String getPatientID()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0020);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Get the Instance of Issuer of Patient ID Macro.Attributes related to IssuerofPatientID Macro will be set in Macro
	 * using the setter methods provided in the Macro.Calling this method multiple times will return the same Marco
	 * Instance that was created at first. Hence, any attributes in this Macro,if set multiple times will contain the value that was
	 * set in the last call to its setter method.
	 * 
	 * @return - object of IssuerofPatientID Macro which the user programmer can populate
	 */
	public IssuerofPatientIDMacro getIssuerofPatientIDMacro()
	{
		if(objIssuerofPatientIDMacro == null)
			objIssuerofPatientIDMacro = new IssuerofPatientIDMacro(objIDataSet);
		return objIssuerofPatientIDMacro; 
	}

	/**
	 * Return the String value of the attribute Issuer Of Patient ID.
	 * 
	 * @return String - returns the issuer of patient ID
	 */
	public String getIssuerOfPatientID()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0021);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Return the String value of the attribute Patient Birth Date.
	 * 
	 * @return String - returns the birth date of the patient
	 */
	public String getPatientBirthDate()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0030);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Return the String value of the attribute Patient Sex.
	 * 
	 * @return String - returns the patient sex
	 */
	public String getPatientSex()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0040);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Quality Control Subject.
	 * 
	 * @return String - String value of Quality Control Subject.
	 */
	public String getQualityControlSubject()
	{Object objectValue = getValue(0x0010,0x0200);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Referenced Patient Photo Sequence.
	 * 
	 * @return - object of Referenced Patient Photo Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public ReferencedPatientPhotoSequence getReferencedPatientPhotoSequence()
	{
		ReferencedPatientPhotoSequence objReferencedPatientPhotoSequence = (ReferencedPatientPhotoSequence)getDicomValue(0x0010,0x1100);
		if(objReferencedPatientPhotoSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objReferencedPatientPhotoSequence = (ReferencedPatientPhotoSequence)objDicomV3Factory.createSequence(0x0010,0x1100, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0010,0x1100, DicomConstants.DCM_DT_SQ, objReferencedPatientPhotoSequence.getValue());
		}
		return objReferencedPatientPhotoSequence;
	}

	/**
	 * This method Returns provides the pre-initialized object of Referenced Patient Sequence
	 * return - object of Referenced Patient Sequence. If the module contans the sequence object
	 * it retruns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 * 
	 * @return ReferencedPatientSequence - returns the Referenced Patient Sequence
	 */
	public ReferencedPatientSequence getReferencedPatientSequence()
	{
		ReferencedPatientSequence objReferencedPatientSequence = (ReferencedPatientSequence)getDicomValue(0x0008, 0x1120);
		if(objReferencedPatientSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objReferencedPatientSequence = (ReferencedPatientSequence)objDicomV3Factory.createSequence(0x0008, 0x1120, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008, 0x1120, DicomConstants.DCM_DT_SQ, objReferencedPatientSequence.getValue());
		}
		return objReferencedPatientSequence;
	}

	/**
	 * Return the String value of the attribute Patient Birth Time.
	 * 
	 * @return String - returns the Birth time of the patient
	 */
	public String getPatientBirthTime()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x0032);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Return the Array of String values of the attribute Other Patient IDs.
	 * 
	 * @return String[] - returns the collection of other patient IDs
	 */
	public String[] getOtherPatientIDs()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x1000);
		if(objValue != null)
			return (String[])objValue;
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Other Patient IDs Sequence.
	 * 
	 * @return - object of Other Patient IDs Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public OtherPatientIDsSequence getOtherPatientIDsSequence()
	{
		OtherPatientIDsSequence objOtherPatientIDsSequence = (OtherPatientIDsSequence)getDicomValue(0x0010,0x1002);
		if(objOtherPatientIDsSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objOtherPatientIDsSequence = (OtherPatientIDsSequence)objDicomV3Factory.createSequence(0x0010,0x1002, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0010,0x1002, DicomConstants.DCM_DT_SQ, objOtherPatientIDsSequence.getValue());
		}
		return objOtherPatientIDsSequence;
	}

	/**
	 * Return the Array of String values of the attribute Other Patient Names.
	 * 
	 * @return String[] - returns the collection of other patient names
	 */
	public String[] getOtherPatientNames()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x1001);
		if(objValue != null)
			return (String[])objValue;
		return null;
	}

	/**
	 * Return the String value of the attribute Ethnic Group.
	 * 
	 * @return String - returns the ethnic group of the patient
	 */
	public String getEthnicGroup()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x2160);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Return the String value of the attribute Patient Comments.
	 * 
	 * @return String - returns the patient comments
	 */
	public String getPatientComments()
	{
		Object objValue = objIDataSet.getValue(0x0010, 0x4000);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Patient Species Description.
	 * 
	 * @return String - String value of Patient Species Description
	 */
	public String getPatientSpeciesDescription()
	{
		Object objectValue = getValue(0x0010, 0x2201);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Patient Species Code Sequence.
	 * 
	 * @return - object of Patient Species Code Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public PatientSpeciesCodeSequence getPatientSpeciesCodeSequence()
	{
		PatientSpeciesCodeSequence objPatientSpeciesCodeSequence = (PatientSpeciesCodeSequence)getDicomValue(0x0010, 0x2202);
		if(objPatientSpeciesCodeSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objPatientSpeciesCodeSequence = (PatientSpeciesCodeSequence)objDicomV3Factory.createSequence(0x0010, 0x2202, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0010, 0x2202, DicomConstants.DCM_DT_SQ, objPatientSpeciesCodeSequence.getValue());
		}
		return objPatientSpeciesCodeSequence;
	}
	
	/**
	 * Retrieves Patient Breed Description.
	 * 
	 * @return String - String value of Patient Breed Description
	 */
	public String getPatientBreedDescription()
	{
		Object objectValue = getValue(0x0010, 0x2292);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Patient Breed Code Sequence.
	 * 
	 * @return - object of Patient Breed Code Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public PatientBreedCodeSequence getPatientBreedCodeSequence()
	{
		PatientBreedCodeSequence objPatientBreedCodeSequence = (PatientBreedCodeSequence)getDicomValue(0x0010, 0x2293);
		if(objPatientBreedCodeSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objPatientBreedCodeSequence = (PatientBreedCodeSequence)objDicomV3Factory.createSequence(0x0010, 0x2293, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0010, 0x2293, DicomConstants.DCM_DT_SQ, objPatientBreedCodeSequence.getValue());
		}
		return objPatientBreedCodeSequence;
	}
	
	/**
	 * This method provides the pre-initialized object of Breed Registration Sequence.
	 * 
	 * @return - object of Breed Registration Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public BreedRegistrationSequence getBreedRegistrationSequence()
	{
		BreedRegistrationSequence objBreedRegistrationSequence = (BreedRegistrationSequence)getDicomValue(0x0010, 0x2294);
		if(objBreedRegistrationSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objBreedRegistrationSequence = (BreedRegistrationSequence)objDicomV3Factory.createSequence(0x0010, 0x2294, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0010, 0x2294, DicomConstants.DCM_DT_SQ, objBreedRegistrationSequence.getValue());
		}
		return objBreedRegistrationSequence;
	}
	
	/**
	 * Retrieves Responsible Person.
	 * 
	 * @return String - String value of Responsible Person
	 */
	public String getResponsiblePerson()
	{
		Object objectValue = getValue(0x0010, 0x2297);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Responsible Person Role.
	 * 
	 * @return String - String value of Responsible Person Role
	 */
	public String getResponsiblePersonRole()
	{
		Object objectValue = getValue(0x0010, 0x2298);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Responsible Organization.
	 * 
	 * @return String - String value of Responsible Organization
	 */
	public String getResponsibleOrganization()
	{
		Object objectValue = getValue(0x0010, 0x2299);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Patient Identity Removed.
	 * 
	 * @return String - String value of Patient Identity Removed.
	 */ 
	public String getPatientIdentityRemoved()
	{
		Object objValue = getValue(0x0012,0x0062);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves Deidentification Method.
	 * 
	 * @return String - String value of Deidentification Method.
	 */
	public String getDeidentificationMethod()
	{
		Object objValue = getValue(0x0012,0x0063);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Deidentification Method Code Sequence.
	 * 
	 * @return - object of Deidentification Method Code Sequence. If the module contains the sequence object
	 * it returns the same otherwise it creates the sequence adds to the module with proper initialization
	 * and then returns the object of sequence
	 */
	public DeidentificationMethodCodeSequence getDeidentificationMethodCodeSequence()
	{
		DeidentificationMethodCodeSequence objDeidentificationMethodCodeSequence = (DeidentificationMethodCodeSequence)getDicomValue(0x0012, 0x0064);
		if(objDeidentificationMethodCodeSequence == null)
		{
			/*
			 * If the sequence object is not present in the DataSet, a new sequence object is created and
			 * the TransferSyntax and DictionaryReader is set into it as it is set in the Module. This ensures that 
			 * the DataElements getting added in the DataSet follow the same TransferSyntax and use the same
			 * DictionaryReader object as that of the module.
			 */
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			objDeidentificationMethodCodeSequence = (DeidentificationMethodCodeSequence)objDicomV3Factory.createSequence(0x0012, 0x0064, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0012, 0x0064, DicomConstants.DCM_DT_SQ, objDeidentificationMethodCodeSequence.getValue());
		}
		return objDeidentificationMethodCodeSequence;
	}


	/* 
	 * This method is used by the Module Iterator to iterate through the DataSet and return only
	 * those elements that belong to the respective Module class whose getVectorOfKeys is called.
	 */
	/**
	 * Returns the vector of keys representing the DataElements
	 * that belong to this module.
	 * 
	 * @return collection of Tags - returns the customized collection containing data element
	 * tags of this modules
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}

	/**
	 * Checks the presence of the specified DataElement in the Patient Module.
	 * 
	 * @param iGroupNumber - Group Number of the Tag
	 * @param iElementNumber - Element Number of the Tag
	 * 
	 * @return - status indicating success/failure of the function
	 */
	public boolean isPresent(int iGroupNumber, int iElementNumber)
	{
		return objIDataSet.isPresent(iGroupNumber, iElementNumber);
	}
}
