/*******************************************************************************
 *  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.DerivationCodeSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedInstanceSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedRTPlanSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedSpatialRegistrationSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedTreatmentRecordSequence;
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.EnumBitsAllocated;
import cdac.medinfo.sdk.dcm30_04.enums.EnumBitsStored;
import cdac.medinfo.sdk.dcm30_04.enums.EnumDoseSummationType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumDoseType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumDoseUnits;
import cdac.medinfo.sdk.dcm30_04.enums.EnumHighBit;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPhotometricInterpretation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPixelRepresentation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSamplesPerPixel;
import cdac.medinfo.sdk.dcm30_04.enums.EnumTissueHeterogeneityCorrection;

import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
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;

// TODO: Auto-generated Javadoc
/**
 * The RT Dose module is used to convey 2D or 3D radiation dose data
 * generated from treatment planning systems or similar devices.
 */
public class RTDoseModule extends Module  
{


	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;


	/**
	 * Instantiates a new rT dose module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	ReferencedSpatialRegistrationSequence objReferencedSpatialRegistrationSequence=null;
	public RTDoseModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0020,0x0013));
		objSingleCollection.add(new Tag(0x0028,0x0002));
		objSingleCollection.add(new Tag(0x0028,0x0004));
		objSingleCollection.add(new Tag(0x0028,0x0100));
		objSingleCollection.add(new Tag(0x0028,0x0101));
		objSingleCollection.add(new Tag(0x0028,0x0102));
		objSingleCollection.add(new Tag(0x0028,0x0103));
		objSingleCollection.add(new Tag(0x3004,0x0002));
		objSingleCollection.add(new Tag(0x3004,0x0004));
		objSingleCollection.add(new Tag(0x3004,0x0006));
		objSingleCollection.add(new Tag(0x3004,0x0008));
		objSingleCollection.add(new Tag(0x3004,0x000A));
		objSingleCollection.add(new Tag(0x3004,0x000C));
		objSingleCollection.add(new Tag(0x3004,0x000E));
		objSingleCollection.add(new Tag(0x3004,0x0014));
		objSingleCollection.add(new Tag(0x300C,0x0002));
	}

	/**
	 * This method 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 - returns validation status as success or failure
	 * 
	 * @throws InvalidModuleException - If validation of Module fails
	 */
	public  boolean validateModule() throws InvalidModuleException
	{

		try
		{		
			if(!isPresent(0x3004,0x0002))
				throw new MandatoryMissingException("3004,0002");
			if(!isPresent(0x3004,0x0004))
				throw new MandatoryMissingException("3004,0004");
			if(!isPresent(0x3004,0x000A))
				throw new MandatoryMissingException("3004,000A");
			if(!isPresent(0x3004,0x000E))
				throw new MandatoryMissingException("3004,000E");

			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0002)))
				throw new ConditionFailedException("0028,0002 is required if element 7FE0,0010 is present");
			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0004)))
				throw new ConditionFailedException("0028,0004 is required if element 7FE0,0010 is present");
			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0100)))
				throw new ConditionFailedException("0028,0100 is required if element 7FE0,0010 is present");
			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0101)))
				throw new ConditionFailedException("0028,0101 is required if element 7FE0,0010 is present");
			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0102)))
				throw new ConditionFailedException("0028,0102 is required if element 7FE0,0010 is present");
			if((isPresent(0x7FE0,0x0010)) && (!isPresent(0x0028,0x0103)))
				throw new ConditionFailedException("0028,0103 is required if element 7FE0,0010 is present");

			String strDoseSummationType = getDoseSummationType();
			if((strDoseSummationType.equalsIgnoreCase(EnumDoseSummationType.ENTIRE_RT_PLAN.getValue())||
					strDoseSummationType.equalsIgnoreCase(EnumDoseSummationType.BEAMS_RT_PLAN.getValue())||
					strDoseSummationType.equalsIgnoreCase(EnumDoseSummationType.BRACHY_APPLICATION_RT_PLAN.getValue())||
					strDoseSummationType.equalsIgnoreCase(EnumDoseSummationType.FRACTION_GROUP_RT_PLAN.getValue())) && !isPresent(0x300C,0x0002))
				throw new ConditionFailedException("300C,0002 is required if element 3004,000A is present");
		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

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

		}
		catch(ConditionFailedException cfe)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(cfe.getMessage());

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

		}
		return true;
	}

	/**
	 * Sets Dose axis units.
	 * Enumerated Values :
	 * GY = Gray,
	 * RELATIVE = dose relative to reference value specified in DVH Normalization Dose Value (3004,0042).
	 * 
	 * @param enumDoseUnits - Enum value of Dose Units
	 */
	public void setDoseUnits(EnumDoseUnits enumDoseUnits)
	{
		/*Accept the Dose Units 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 Data Set
		 */
		String strDoseUnits = enumDoseUnits.getValue();
		addDataElement(0x3004,0x0002, DicomConstants.DCM_DT_CS, strDoseUnits);
	}

	/**
	 * Retrieves Dose axis units.
	 * 
	 * @return String - String value of Dose Units.
	 */
	public String getDoseUnits()
	{Object objectValue = getValue(0x3004,0x0002);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Samples per Pixel.
	 * Number of samples (planes) in this image.
	 * 
	 * @param enumSamplesperPixel - Short value of Samples per Pixel.
	 */
	public void setSamplesperPixel(EnumSamplesPerPixel enumSamplesperPixel)
	{
		/*Accept Number of samples (planes) in this image in short format of type US.
		 * 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(0x0028, 0x0002, DicomConstants.DCM_DT_US, enumSamplesperPixel.getValue());
	}

	/**
	 * Retrieves Samples per Pixel.
	 * 
	 * @return the samplesper pixel
	 */
	public short getSamplesperPixel()
	{Object objectValue = getValue(0x0028,0x0002);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets Photometric Interpretation.
	 * Specifies the intended interpretation of the pixel data
	 * 
	 * @param enumPhotometricInterpretation - String value of Photometric Interpretation.
	 */
	public void setPhotometricInterpretation(EnumPhotometricInterpretation enumPhotometricInterpretation)
	{
		/*Accept Specifies the intended interpretation of the pixel data in String format of type ST.
		 * 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(0x0028, 0x0004, DicomConstants.DCM_DT_CS, enumPhotometricInterpretation.getValue());
	}

	/**
	 * Retrieves Photometric Interpretation.
	 * 
	 * @return the photometric interpretation
	 */
	public String getPhotometricInterpretation()
	{Object objectValue = getValue(0x0028,0x0004);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Bits Allocated.
	 * Number of bits allocated for each pixel sample.
	 * Each sample shall have the same number of bits allocated.
	 * 
	 * @param enumBitsAllocated the enum bits allocated
	 */
	public void setBitsAllocated(EnumBitsAllocated enumBitsAllocated)
	{
		/*Accept bits allocated for each pixel in this image in short format of type US.
		 * 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(0x0028, 0x0100, DicomConstants.DCM_DT_US, enumBitsAllocated.getValue());
	}

	/**
	 * Retrieves Bits Allocated.
	 * 
	 * @return the bits allocated
	 */
	public short getBitsAllocated()
	{Object objectValue = getValue(0x0028,0x0100);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets Bits Stored.
	 * Number of bits stored for each pixel sample.
	 * Each sample shall have the same number of bits stored.
	 * 
	 * @param enumBitsStored the enum bits stored
	 */
	public void setBitsStored(EnumBitsStored enumBitsStored)
	{
		/*Accept bits stored for each pixel in this image in short format of type US.
		 * 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(0x0028, 0x0101, DicomConstants.DCM_DT_US, enumBitsStored.getValue());
	}

	/**
	 * Retrieves Bits Stored.
	 * 
	 * @return the bits stored
	 */
	public short getBitsStored()
	{Object objectValue = getValue(0x0028,0x0101);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets High Bit.
	 * Most significant bit for each pixel sample.
	 * Each sample shall have the same high bit.
	 * 
	 * @param enumHighBit - short value of High Bit.
	 */
	public void setHighBit(EnumHighBit enumHighBit)
	{
		/*Accept Most significant bit for pixel in this image in short format of type US.
		 * 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(0x0028, 0x0102, DicomConstants.DCM_DT_US, enumHighBit.getValue());
	}

	/**
	 * Retrieves High Bit.
	 * 
	 * @return the high bit
	 */
	public short getHighBit()
	{Object objectValue = getValue(0x0028,0x0102);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets Pixel Representation.
	 * Data representation of the pixel samples.
	 * Each sample shall have the same pixel representation.
	 * 
	 * @param enumPixelRepresentation the enum pixel representation
	 */
	public void setPixelRepresentation(EnumPixelRepresentation enumPixelRepresentation)
	{
		/*Accept Data representation of pixel in this image in short format of type US.
		 * 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(0x0028, 0x0103, DicomConstants.DCM_DT_US, enumPixelRepresentation.getValue());
	}

	/**
	 * Retrieves Pixel Representation.
	 * 
	 * @return the pixel representation
	 */
	public short getPixelRepresentation()
	{Object objectValue = getValue(0x0028,0x0103);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Sets Type of dose.
	 * 
	 * @param enumDoseType - Enum value of Dose Type.
	 */
	public void setDoseType(EnumDoseType enumDoseType)
	{
		/* Accept Structure Set Label 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 Data Set
		 */
		String strDoseType = enumDoseType.getValue();
		addDataElement(0x3004,0x0004, DicomConstants.DCM_DT_CS, strDoseType);
	}

	/**
	 * Retrieves Dose Type.
	 * 
	 * @return the dose type
	 */
	public String getDoseType()
	{Object objectValue = getValue(0x3004,0x0004);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	/**
	 * Sets the Spatial Transform of Dose
	 * @param strSpatialTransformOfDose Specifies type of the value Spatial Transform of Dose
	 */
	public void setSpatialTransformOfDose(String strSpatialTransformOfDose)
	{
		/*Accept the Spatial Transform of Dose 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 Data Set
		 */
		addDataElement(0x3004,0x0005, DicomConstants.DCM_DT_CS,strSpatialTransformOfDose);
	}
	/**
	 * Retrieves type of the value Spatial Transform of Dose
	 * @return String - Type of the value Spatial Transform of Dose
	 */
	public String getSpatialTransformOfDose()
	{
		Object objValue = getValue(0x0040, 0x0005);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Retrieves sequence of Referenced SpatialRegistration 
	 * 
	 * @return - instance of {@link ReferencedRTPlanSequence}.
	 */
	public ReferencedSpatialRegistrationSequence getReferencedSpatialRegistrationSequence()
	{
		ReferencedSpatialRegistrationSequence objReferencedSpatialRegistrationSequence = (ReferencedSpatialRegistrationSequence)getDicomValue(0x300C,0002);
		if(objReferencedSpatialRegistrationSequence == 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();
			objReferencedSpatialRegistrationSequence = (ReferencedSpatialRegistrationSequence)objDicomV3Factory.createSequence(0x0070,0x0404, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0070,0x0404, DicomConstants.DCM_DT_SQ, objReferencedSpatialRegistrationSequence.getValue());
		}
		return objReferencedSpatialRegistrationSequence;
	}
	/**
	 * Sets Instance Number.
	 * A number that identifies this object instance.
	 * 
	 * @param strInstanceNumber - String value of Instance Number.
	 */
	public void setInstanceNumber(String strInstanceNumber)
	{
		/* Accept Instance Numberin String format of type IS.
		 * 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(0x0020, 0x0013, DicomConstants.DCM_DT_IS, strInstanceNumber);
	}

	/**
	 * Retrieves Instance Number.
	 * 
	 * @return the instance number
	 */
	public String getInstanceNumber()
	{Object objectValue = getValue(0x0020,0x0013);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Dose Comment.
	 * User-defined comments for dose data.
	 * 
	 * @param strDoseComment - String value of Dose Comment.
	 */
	public void setDoseComment(String strDoseComment)
	{
		/* Accept Structure Set Label in String 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 Data Set
		 */
		addDataElement(0x3004,0x0006, DicomConstants.DCM_DT_LO, strDoseComment);
	}

	/**
	 * Retrieves Dose Comment.
	 * 
	 * @return the dose comment
	 */
	public String getDoseComment()
	{Object objectValue = getValue(0x3004,0x0006);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Normalization Point.
	 * 
	 * @param arrstrNormalizationPoint - String value of Normalization Point.
	 */
	public void setNormalizationPoint(String[] arrstrNormalizationPoint)
	{
		/* Accept Structure Set Label 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(0x3004,0x0008, DicomConstants.DCM_DT_DS, arrstrNormalizationPoint);
	}

	/**
	 * Retrieves Normalization Point.
	 * 
	 * @return the normalization point
	 */
	public String[] getNormalizationPoint()
	{Object objectValue = getValue(0x3004,0x0008);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Sets Type of dose summation.
	 * 
	 * @param enumDoseSummationType - Enum value of Dose Summation Type.
	 */
	public void setDoseSummationType(EnumDoseSummationType enumDoseSummationType)
	{
		/* Accept Structure Set Label 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 Data Set
		 */
		addDataElement(0x3004,0x000A, DicomConstants.DCM_DT_CS, enumDoseSummationType.getValue());
	}

	/**
	 * Retrieves Dose Summation Type.
	 * 
	 * @return the dose summation type
	 */
	public String getDoseSummationType()
	{
		 Object objValue = getValue(0x3004,0x000A);
   if(objValue!=null)
      return objValue.toString();
   return null;

	}

	
	/**
	 * Sets Grid Frame Offset Vector.
	 * 
	 * @param arrstrGridFrameOffsetVector - String value of Grid Frame Offset Vector.
	 */
	public void setGridFrameOffsetVector(String[] arrstrGridFrameOffsetVector)
	{
		/* Accept Structure Set Label 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(0x3004,0x000C, DicomConstants.DCM_DT_DS, arrstrGridFrameOffsetVector);
	}

	/**
	 * Retrieves Grid Frame Offset Vector.
	 * 
	 * @return the grid frame offset vector
	 */
	public String[] getGridFrameOffsetVector()
	{
		Object objectValue = getValue(0x3004,0x000C);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Sets Scaling factor.
	 * 
	 * @param strDoseGridScaling - String value of Dose Grid Scaling.
	 */
	public void setDoseGridScaling(String strDoseGridScaling)
	{
		/* Accept Structure Set Label 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(0x3004,0x000E, DicomConstants.DCM_DT_DS, strDoseGridScaling);
	}

	/**
	 * Retrieves Dose Grid Scaling.
	 * 
	 * @return the dose grid scaling
	 */
	public String getDoseGridScaling()
	{
		 Object objValue = getValue(0x3004,0x000E);
   if(objValue!=null)
      return objValue.toString();
   return null;

	}

	/**
	 * Sets Tissue Heterogeneity Correction.
	 * Specifies a list of patient heterogeneity characteristics used for calculating dose.
	 * 
	 * @param enumTissueHeterogeneityCorrection - Enum value of Tissue Heterogeneity Correction.
	 */
	public void setTissueHeterogeneityCorrection(EnumTissueHeterogeneityCorrection[] enumTissueHeterogeneityCorrection)
	{
		/* Accept Structure Set Label 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 Data Set
		 */
		//int intSize = enumTissueHeterogeneityCorrection.length;
		String[] arrstrTissueHeterogeneityCorrection = new String[enumTissueHeterogeneityCorrection.length];
		for(int i=0;i < enumTissueHeterogeneityCorrection.length ; i++)
		{
			arrstrTissueHeterogeneityCorrection[i] = enumTissueHeterogeneityCorrection[i].getValue();
		}
		addDataElement(0x3004,0x0014, DicomConstants.DCM_DT_CS, arrstrTissueHeterogeneityCorrection);
	}

	/**
	 * Retrieves Tissue Heterogeneity Correction.
	 * 
	 * @return the tissue heterogeneity correction
	 */
	public String[] getTissueHeterogeneityCorrection()
	{Object objectValue = getValue(0x3004,0x0014);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}

	/**
	 * Retrieves sequence of one Class/Instance pair describing RT Plan associated with dose.
	 * 
	 * @return - instance of {@link ReferencedRTPlanSequence}.
	 */
	public ReferencedRTPlanSequence getReferencedRTPlanSequence()
	{
		ReferencedRTPlanSequence objReferencedRTPlanSequence = (ReferencedRTPlanSequence)getDicomValue(0x300C,0002);
		if(objReferencedRTPlanSequence == 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();
			objReferencedRTPlanSequence = (ReferencedRTPlanSequence)objDicomV3Factory.createSequence(0x300C,0x0002, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x300C,0x0002, DicomConstants.DCM_DT_SQ, objReferencedRTPlanSequence.getValue());
		}
		return objReferencedRTPlanSequence;
	}
	
	/**
	 * Retrieves sequence of Referenced TreatmentRecord Sequence
	 * 
	 * @return - instance of {@link objRReferencedTreatmentRecordSequence}.
	 */
	public ReferencedTreatmentRecordSequence getReferencedTreatmentRecordSequence()
	{
		ReferencedTreatmentRecordSequence objReferencedTreatmentRecordSequence = (ReferencedTreatmentRecordSequence)getDicomValue(0x300C,0002);
		if(objReferencedTreatmentRecordSequence == 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();
			objReferencedTreatmentRecordSequence = (ReferencedTreatmentRecordSequence)objDicomV3Factory.createSequence(0x3008,0x0030, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x3008,0x0030, DicomConstants.DCM_DT_SQ, objReferencedTreatmentRecordSequence.getValue());
		}
		return objReferencedTreatmentRecordSequence;
	}

	
	/**
	 * Retrieves sequence of DerivationCodeSequence
	 * 
	 * @return - instance of {@link DerivationCodeSequence}.
	 */
	public DerivationCodeSequence getDerivationCodeSequence()
	{
		DerivationCodeSequence objDerivationCodeSequence = (DerivationCodeSequence)getDicomValue(0x300C,0002);
		if(objDerivationCodeSequence == 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();
			objDerivationCodeSequence = (DerivationCodeSequence)objDicomV3Factory.createSequence(0x0008,0x9215, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x9215, DicomConstants.DCM_DT_SQ, objDerivationCodeSequence.getValue());
		}
		return objDerivationCodeSequence;
	}
	
	/**
	 * Retrieves sequence of ReferencedInstanceSequence
	 * 
	 * @return - instance of {@link ReferencedInstanceSequence}.
	 */
	public ReferencedInstanceSequence getReferencedInstanceSequence()
	{
		ReferencedInstanceSequence objReferencedInstanceSequence = (ReferencedInstanceSequence)getDicomValue(0x300C,0002);
		if(objReferencedInstanceSequence == 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();
			objReferencedInstanceSequence = (ReferencedInstanceSequence)objDicomV3Factory.createSequence(0x0008,0x114A, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x114A, DicomConstants.DCM_DT_SQ, objReferencedInstanceSequence.getValue());
		}
		return objReferencedInstanceSequence;
	}
	/**
	 * This method returns the vector of keys representing the DataElements
	 * that belong to this module.
	 * 
	 * @return vector of Tags - returns the vector containing the collection of tags.
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}
}
