/*******************************************************************************
 *  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.CommonCTOrMRImageDescriptionMacro;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.IconImageSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedImageEvidenceSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedRawDataSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.ReferencedWaveformSequence;
import cdac.medinfo.sdk.dcm30_04.baselibs.SourceImageEvidenceSequence;
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.EnumBurnedInAnnotation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumContentQualification;
import cdac.medinfo.sdk.dcm30_04.enums.EnumLossyImageCompression;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRecognizableVisualFeatures;
import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidMacroException;
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;

/**
* This module is used for Enhanced PET Image Module.
*/
public class EnhancedPETImageModule extends Module{
	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;
	/**
	 * The obj code sequence macro.
	 */
	CommonCTOrMRImageDescriptionMacro objCommonCTOrMRImageDescriptionMacro = null;

	
	public EnhancedPETImageModule(IDataSet objIDataSet) {
		super(objIDataSet);
		
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0008,0x0008));
		objSingleCollection.add(new Tag(0x0020,0x0012));
		objSingleCollection.add(new Tag(0x0008,0x002A));
		objSingleCollection.add(new Tag(0x0018,0x9073));
		objSingleCollection.add(new Tag(0x0008,0x9121));
		objSingleCollection.add(new Tag(0x0008,0x113A));
		objSingleCollection.add(new Tag(0x0008,0x9092));
		objSingleCollection.add(new Tag(0x0008,0x9154));
		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(0x0018,0x9004));
		objSingleCollection.add(new Tag(0x0020,0x4000));
		objSingleCollection.add(new Tag(0x0028,0x0301));
		objSingleCollection.add(new Tag(0x0028,0x0302));
		objSingleCollection.add(new Tag(0x0028,0x2110));
		objSingleCollection.add(new Tag(0x0028,0x2112));
		objSingleCollection.add(new Tag(0x0028,0x2114));
		objSingleCollection.add(new Tag(0x2050,0x0020));
		objSingleCollection.add(new Tag(0x0088,0x0200));
	}

	@Override
	public boolean validateModule() {
		try
		{			
			if(!isPresent(0x0008,0x0008))
				throw new MandatoryMissingException("0008,0008");
			if(isPresent(0x0008,0x9092) && (!isPresent(0x0008,0x1140)))
					throw new ConditionFailedException("0x0008,0x1140") ;
			if(isPresent(0x0008,0x9154) && (!isPresent(0x0008,0x2112)))
				throw new ConditionFailedException("0x0008,0x9154") ;
			if(!isPresent(0x0008,0x0002))
				throw new MandatoryMissingException("0008,0002");
			if(!isPresent(0x0008,0x0004))
				throw new MandatoryMissingException("0008,0004");
			if(!isPresent(0x0008,0x0100))
				throw new MandatoryMissingException("0008,0100");
			if(!isPresent(0x0008,0x0101))
				throw new MandatoryMissingException("0008,0101");
			if(!isPresent(0x0008,0x0102))
				throw new MandatoryMissingException("0008,0102");
			if(!isPresent(0x0018,0x9004))
				throw new MandatoryMissingException("0018,9004");
			if(!isPresent(0x0008,0x0008))
				throw new MandatoryMissingException("0008,0008");
			if(!isPresent(0x2050,0x0020))
				throw new MandatoryMissingException("2050,0020");
			try
			{
				getCommonCTOrMRImageDescriptionMacro().validate();
			}
			catch(InvalidMacroException ve)
			{
				if(DicomConfig.createInstance().isLoggingOn())
					DicomLogger.getLogger().log(ve.getMessage());

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

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

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

			}
			
		}
		catch(MandatoryMissingException mme)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

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

		}
		return true;
	}
	
	/**
	 * Sets the Value Type Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param strImageType Specifies type of the value encoded in this Item
	 */
	public void setImageType(String strImageType)
	{
		/*Accept the Value Type 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(0x0008,0x0008,DicomConstants.DCM_DT_CS, strImageType);
		
		
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getImageType()
	{
		Object objValue = getValue(0x0008,0x0008);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Get the Instance of CommonCT Or MRImageDescriptionMacro.Attributes related to Code Sequence 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 code sequence macro which the user programmer can populate
	 */
	public CommonCTOrMRImageDescriptionMacro getCommonCTOrMRImageDescriptionMacro()
	{
		if(objCommonCTOrMRImageDescriptionMacro == null)
			objCommonCTOrMRImageDescriptionMacro = new CommonCTOrMRImageDescriptionMacro(objIDataSet);
		return objCommonCTOrMRImageDescriptionMacro; 
	}

	/**
	 * Sets Referenced Reference Image Number. Uniquely identifies Reference Image to which planned verification image is related, 
	 * specified by Reference Image Number (300A,00C8) within Referenced Reference Image Sequence (300A,0042).
	 * @param strReferencedReferenceImageNumber String value of Referenced Reference Image Number.
	 */
	public void setAcquisitionNumber (String strReferencedReferenceImageNumber )
	{
		/*Accept the Referenced Reference Image Number  in 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,0x0012,DicomConstants.DCM_DT_IS, strReferencedReferenceImageNumber);
	}
	/**
	 * Retrieves Referenced Reference Image Number. Uniquely identifies Reference Image to which planned verification image is related, 
	 * specified by Reference Image Number (300A,00C8) within Referenced Reference Image Sequence (300A,0042).
	 * @return String - value of Referenced Reference Image Number.
	 */
	public String getAcquisitionNumber()
	{
		Object objValue = getValue(0x0020,0x0012);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets Date and Time of verification by the Verifying Observer Name (0040,A075).
	 * @param strVerificationDateTime String value of Verification DateTime
	 */
	public void setAcquisitionDateTime(String strAcquisitionDateTime)
	{
		/* Accept the Verification DateTime of type DT.
		 * 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(0x0008,0x002A,DicomConstants.DCM_DT_DT, strAcquisitionDateTime);
	}

	/**
	 * Retrieves Verification DateTime
	 * @return String - value of Verification DateTime
	 */
	public String getAcquisitionDateTime()
	{
		Object objValue = getValue(0x0008,0x002A);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets the Minimal value of Chemical Shift Frequency in ppm.
	 * @param dblChemicalShiftsMinimumIntegrationLimitOnppm Double value of coordinates
	 */
	public void setAcquisitionDuration(double dblAcquisitionDuration)
	{
		/*Accept the Chemical Shifts Minimum Integration Limit in ppm in double format of type FD.
		 * 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(0x0018,0x9073,DicomConstants.DCM_DT_FD, dblAcquisitionDuration);
	}
	/**
	 * Retrieves the Minimal value of Chemical Shift Frequency in ppm.
	 * @return double - double value of ChemicalShiftsMinimumIntegrationLimitOnppm
	 */
	public double getAcquisitionDuration()
	{
		Object objValue = getValue(0x0018,0x9073);
		if(objValue != null)
			return Double.parseDouble(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * This method provides the pre-initialized object of Referenced Visit Sequence.
	 * 
	 * @return - object of Referenced Visit 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 ReferencedRawDataSequence getReferencedRawDataSequence()
	{
		ReferencedRawDataSequence objReferencedRawDataSequence = (ReferencedRawDataSequence)getDicomValue(0x0008,0x9121);
		if(objReferencedRawDataSequence == 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();
			objReferencedRawDataSequence = (ReferencedRawDataSequence)objDicomV3Factory.createSequence(0x0008,0x9121, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x9121, DicomConstants.DCM_DT_SQ, objReferencedRawDataSequence.getValue());
		}
		return objReferencedRawDataSequence;
	}
	
	
	/**
	 * This method provides the pre-initialized object of Referenced Visit Sequence.
	 * 
	 * @return - object of Referenced Visit 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 ReferencedWaveformSequence getReferencedWaveformSequence()
	{
		ReferencedWaveformSequence objReferencedWaveformSequence = (ReferencedWaveformSequence)getDicomValue(0x0008,0x113A);
		if(objReferencedWaveformSequence == 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();
			objReferencedWaveformSequence = (ReferencedWaveformSequence)objDicomV3Factory.createSequence(0x0008,0x113A, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x113A, DicomConstants.DCM_DT_SQ, objReferencedWaveformSequence.getValue());
		}
		return objReferencedWaveformSequence;
	}
	
	/**
	 * This method provides the pre-initialized object of Referenced Visit Sequence.
	 * 
	 * @return - object of Referenced Visit 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 ReferencedImageEvidenceSequence getReferencedImageEvidenceSequence()
	{
		ReferencedImageEvidenceSequence objReferencedImageEvidenceSequence = (ReferencedImageEvidenceSequence)getDicomValue(0x0008,0x9092);
		if(objReferencedImageEvidenceSequence == 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();
			objReferencedImageEvidenceSequence = (ReferencedImageEvidenceSequence)objDicomV3Factory.createSequence(0x0008,0x9092, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x9092, DicomConstants.DCM_DT_SQ, objReferencedImageEvidenceSequence.getValue());
		}
		return objReferencedImageEvidenceSequence;
	}
	/**
	 * This method provides the pre-initialized object of SourceImageEvidenceSequence.
	 * 
	 * @return - object of Referenced Visit 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 SourceImageEvidenceSequence getSourceImageEvidenceSequence()
	{
		SourceImageEvidenceSequence objSourceImageEvidenceSequence = (SourceImageEvidenceSequence)getDicomValue(0x0008,0x9154);
		if(objSourceImageEvidenceSequence == 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();
			objSourceImageEvidenceSequence = (SourceImageEvidenceSequence)objDicomV3Factory.createSequence(0x0008,0x9154, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0008,0x9154, DicomConstants.DCM_DT_SQ, objSourceImageEvidenceSequence.getValue());
		}
		return objSourceImageEvidenceSequence;
	}
	
	
	/**
	 * Sets Number of significant bits within the waveform samples
	 * @param SamplesPerPixel short value of Number of significant bits
	 */
	public void setSamplesPerPixel(short shSamplesPerPixel)
	{
		/* Accept the WaveformBitsStored 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, shSamplesPerPixel);
	}

	/**
	 * Retrieves Number of significant bits within the waveform samples
	 * @return short - short value of Number of significant bits
	 */
	public short getSamplesPerPixel()
	{
		Object objValue = getValue(0x0028,0x0002);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Sets the Value Type Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param strValueType Specifies type of the value encoded in this Item
	 */
	public void setPhotometricInterpretation(String strPhotometricInterpretation)
	{
		/*Accept the Value Type 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(0x0028,0x0004,DicomConstants.DCM_DT_US, strPhotometricInterpretation);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getPhotometricInterpretation()
	{
		Object objValue = getValue(0x0028,0x0004);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Number of significant bits within the waveform samples
	 * @param shWaveformBitsStored short value of Number of significant bits
	 */
	public void setBitsAllocated(short shBitsAllocated)
	{
		/* Accept the WaveformBitsStored 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, shBitsAllocated);
	}

	/**
	 * Retrieves Number of significant bits within the waveform samples
	 * @return short - short value of Number of significant bits
	 */
	public short getBitsAllocated()
	{
		Object objValue = getValue(0x0028,0x0100);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	
	
	
	/**
	 * Sets Number of significant bits within the waveform samples
	 * @param shWaveformBitsStored short value of Number of significant bits
	 */
	public void setBitsStored(short shBitsStored)
	{
		/* Accept the WaveformBitsStored 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, shBitsStored);
	}

	/**
	 * Retrieves Number of significant bits within the waveform samples
	 * @return short - short value of Number of significant bits
	 */
	public short getBitsStored()
	{
		Object objValue = getValue(0x0028,0x0101);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	
	
	
	/**
	 * Sets Number of significant bits within the waveform samples
	 * @param shWaveformBitsStored short value of Number of significant bits
	 */
	public void setWaveformBitsStored(short shHighBit)
	{
		/* Accept the WaveformBitsStored 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, shHighBit);
	}

	/**
	 * Retrieves Number of significant bits within the waveform samples
	 * @return short - short value of Number of significant bits
	 */
	public short getHighBit()
	{
		Object objValue = getValue(0x0028,0x0102);
		if(objValue != null)
			return Short.parseShort(objValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Sets the Value Type Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param strValueType Specifies type of the value encoded in this Item
	 */
	public void setContentQualification(EnumContentQualification enumContentQualification)
	{
		/*Accept the Value Type 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(0x0018, 0x9004,DicomConstants.DCM_DT_US, enumContentQualification);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getContentQualification()
	{
		Object objValue = getValue(0x0018, 0x9004);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets free form text description of Configuration Information (2010,0150) supported by the printer.
	 * @param strConfigurationInformationDescription String value of Configuration Information Description.
	 */
	public void setImageComments(String strImageComments)
	{
		/* Accept Configuration Information Description of type LT.
		 * 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, 0x4000,DicomConstants.DCM_DT_US, strImageComments);
	}

	/**
	 * Retrieves description of Configuration Information (2010,0150) supported by the printer.
	 * @return String - value of description of Configuration Information (2010,0150) supported by the printer.
	 */
	public String getImageComments()
	{
		Object objValue = getValue(0x0020, 0x4000);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets the BurnedInAnnotation Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param enumBurnedInAnnotation Specifies type of the value encoded in this Item
	 */
	public void setBurnedInAnnotation(EnumBurnedInAnnotation enumBurnedInAnnotation)
	{
		/*Accept the Value Type 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(0x0028, 0x0301,DicomConstants.DCM_DT_US, enumBurnedInAnnotation);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getBurnedInAnnotation()
	{
		Object objValue = getValue(0x0028, 0x0301);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets the BurnedInAnnotation Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param enumBurnedInAnnotation Specifies type of the value encoded in this Item
	 */
	public void setRecognizableVisualFeatures(EnumRecognizableVisualFeatures enumRecognizableVisualFeatures)
	{
		/*Accept the Value Type 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(0x0028, 0x0302,DicomConstants.DCM_DT_US, enumRecognizableVisualFeatures);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getRecognizableVisualFeatures()
	{
		Object objValue = getValue(0x0028, 0x0302);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets the BurnedInAnnotation Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param enumBurnedInAnnotation Specifies type of the value encoded in this Item
	 */
	public void setLossyImageCompression(EnumLossyImageCompression enumLossyImageCompression)
	{
		/*Accept the Value Type 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(0x0028, 0x2110,DicomConstants.DCM_DT_US, enumLossyImageCompression);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getLossyImageCompression()
	{
		Object objValue = getValue(0x0028, 0x2110);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets Slice Thickness.Uniquely identifies Slice Thickness(0018,0050) in Pixel Measures Sequence(0028,9110).
	 * @param strSliceThickness String value of Slice Thickness.
	 */
	public void setLossyImageCompressionRatio(String strLossyImageCompressionRatio)
	{
		/*Accept the SliceThickness 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(0x0028, 0x2112,DicomConstants.DCM_DT_US, strLossyImageCompressionRatio);
	}
	/**
	 * Retrieves Slice Thickness.
	 * @return String - value of Slice Thickness.
	 */
	public String getLossyImageCompressionRatio()
	{
		Object objValue = getValue(0x0028,0x2112);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets the BurnedInAnnotation Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param enumBurnedInAnnotation Specifies type of the value encoded in this Item
	 */
	public void setLossyImageCompressionMethod(String strLossyImageCompressionMethod)
	{
		/*Accept the Value Type 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(0x0028, 0x2114,DicomConstants.DCM_DT_US, strLossyImageCompressionMethod);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getLossyImageCompressionMethod()
	{
		Object objValue = getValue(0x0028, 0x2114);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets the BurnedInAnnotation Defined in Terms of TEXT,NUMERIC,CODE,DATE,TIME,PNAME
	 * @param enumBurnedInAnnotation Specifies type of the value encoded in this Item
	 */
	public void setPresentationLUTShape(String strPresentationLUTShape)
	{
		/*Accept the Value Type 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(0x2050, 0x0020,DicomConstants.DCM_DT_US, strPresentationLUTShape);
	}
	/**
	 * Retrieves type of the value encoded in this Item
	 * @return String - Type of the value encoded in this Item
	 */
	public String getPresentationLUTShape()
	{
		Object objValue = getValue(0x2050, 0x0020);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * This method provides the pre-initialized object of Referenced Visit Sequence.
	 * 
	 * @return - object of Referenced Visit 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 IconImageSequence getIconImageSequence()
	{
		IconImageSequence objIconImageSequence = (IconImageSequence)getDicomValue(0x0088,0x0200);
		if(objIconImageSequence == 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();
			objIconImageSequence = (IconImageSequence)objDicomV3Factory.createSequence(0x0088,0x0200, objITransferSyntax, objIDictionaryReader);
			
			// This will add Data Element of SQ to the DataSet.
			addDataElement(0x0088,0x0200, DicomConstants.DCM_DT_SQ, objIconImageSequence.getValue());
		}
		return objIconImageSequence;
	}
}
