/*******************************************************************************
 *  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.BasicPixelSpacingCalibrationMacro;
import cdac.medinfo.sdk.dcm30_04.baselibs.GeneralAnatomyMandatoryMacro;
import cdac.medinfo.sdk.dcm30_04.baselibs.RealWorldValueMappingMacro;
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.EnumBurnedInAnnotation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumHighBit;
import cdac.medinfo.sdk.dcm30_04.enums.EnumImageLaterality;
import cdac.medinfo.sdk.dcm30_04.enums.EnumLossyImageCompression;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPhotometricInterpretation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPixelRepresentation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRecognizableVisualFeatures;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSamplesPerPixel;

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 Corneal Topography Map Image Module.
*/
public class CornealTopographyMapImageModule extends Module
{
	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;


	/**
	 * Instantiates a new CornealTopographyMapImageModule
	 * 
	 * @param objIDataSet the obj i data set
	 */
	BasicPixelSpacingCalibrationMacro objBasicPixelSpacingCalibrationMacro=null;
	GeneralAnatomyMandatoryMacro objGeneralAnatomyMandatoryMacro=null;
	RealWorldValueMappingMacro objRealWorldValueMappingMacro=null;
	
	public CornealTopographyMapImageModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0020, 0x0013));
		objSingleCollection.add(new Tag(0x0008, 0x0023));
		objSingleCollection.add(new Tag(0x0008, 0x0033));
		objSingleCollection.add(new Tag(0x0008, 0x0008));
		objSingleCollection.add(new Tag(0x0028, 0x0002));
		objSingleCollection.add(new Tag(0x0028, 0x0004));
		objSingleCollection.add(new Tag(0x0028, 0x0103));
		
		objSingleCollection.add(new Tag(0x0028, 0x0034));
		objSingleCollection.add(new Tag(0x0028,0x0100));
		objSingleCollection.add(new Tag(0x0028,0x0101));
		objSingleCollection.add(new Tag(0x0028,0x0102));
		
		objSingleCollection.add(new Tag(0x0028,0x2110));
		objSingleCollection.add(new Tag(0x0028,0x2112));		
		objSingleCollection.add(new Tag(0x0028,0x2114));
		objSingleCollection.add(new Tag(0x0028,0x0301));
		objSingleCollection.add(new Tag(0x0028,0x0302));
		objSingleCollection.add(new Tag(0x0020,0x0062));

	}

	/* For normalized IODs, the type(Mandatory/Optional) of a Module depends upon the
	 * Requirement Type which defines if this module is required by a SCP class or an
	 * SCP class. Hence,the validation of Modules in a Normalized IOD totally depends 
	 * upon the decision that the is it an SCU/SCP that needs the module.Also, Type of the Modules
	 * describes the type of the Attributes inside the Module. Ex: Mandatory Modules contain Attributes that are
	 * included in all SOP Instances employing this IOD.
	 * Decision on implementation of this kind of validation is yet to be done. Hence,
	 * i am putting a empty validate method.
	 * @return - returns validation status as success or failure 
	 * @throws InvalidModuleException - If validation of Module fails 	 
	 */
	/* (non-Javadoc)
	 * @see cdac.medinfo.sdk.dcm30_04.dicommodel.modules.Module#validateModule()
	 */
	public boolean validateModule() throws InvalidModuleException
	{
		try
		{			
			if(!isPresent(0x0020, 0x0013))
				throw new MandatoryMissingException("(0020,0013");
			if(!isPresent(0x0008, 0x0023))
				throw new MandatoryMissingException("0008,0023");
			 if(!isPresent(0x0008, 0x0033))
				throw new MandatoryMissingException("0008,0033)");
			 if(!isPresent(0x0008, 0x002A))
				throw new MandatoryMissingException("0008,002A");	
			 if(!isPresent(0x0008, 0x0008))
				throw new MandatoryMissingException("0008,0008");
			 if(!isPresent(0x0028, 0x0002))
				throw new MandatoryMissingException("0028,0002");
			 if(!isPresent(0x0028, 0x0004))
				throw new MandatoryMissingException("0028,0004");
			 if(!isPresent(0x0028, 0x0103))
				throw new MandatoryMissingException("0028,0103");
			 if(!isPresent(0x0028, 0x0034))
				throw new MandatoryMissingException("0028,0034");			 
			 if(!isPresent(0x0028, 0x0100))
				throw new MandatoryMissingException("0028,0100");
			 if(!isPresent(0x0028, 0x0101))
				throw new MandatoryMissingException("0028,0101");
			 if(!isPresent(0x0028, 0x0102))
				throw new MandatoryMissingException("0028,0102");
			 if(!isPresent(0x0028, 0x2110))
				throw new MandatoryMissingException("0028,2110");
			 if(!isPresent(0x0028, 0x2112))
				throw new MandatoryMissingException("0028,2112");
			 if(!isPresent(0x0028, 0x2114))
				throw new MandatoryMissingException("0028,2114");
			 if(!isPresent(0x0028, 0x0301))
				throw new MandatoryMissingException("0028,0301");
			 if(!isPresent(0x0028, 0x0302))
				throw new MandatoryMissingException("0028,0302");
			 if(!isPresent(0x0020, 0x0062))
				throw new MandatoryMissingException("0020,0062");

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

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

		}
		return true;
	}

	/**
	 * Sets a number that identifies this presentation (SOP Instance).
	 * 
	 * @param strInstanceNumber String value of number that identifies this presentation
	 */
	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 a number that identifies this presentation.
	 * 
	 * @return String - String value of a number that identifies this presentation.
	 */
	public String getInstanceNumber()
	{
		Object objValue = objIDataSet.getValue(0x0020, 0x0013);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets date the data creation was started.
	 * @param strContentDate String value of date the data creation was started.
	 */
	public void setContentDate(String strContentDate)
	{
		/* Accept the Content Date 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 Data Set
		 */
		addDataElement(0x0008, 0x0023, DicomConstants.DCM_DT_DA,strContentDate);
	}

	/**
	 * Retrieves date the data creation was started.
	 * @return String - value of date the data creation was started.
	 */
	public String getContentDate()
	{
		Object objValue = getValue(0x0008, 0x0023);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets time the data creation was started.
	 * @param strContentTime String value of time the data creation was started.
	 */
	public void setContentTime(String strContentTime)
	{
		/* Accept the Content Time of type TM.
		 * 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, 0x0033, DicomConstants.DCM_DT_TM,strContentTime);
	}

	/**
	 * Retrieves time the data creation was started.
	 * @return String - value of time the data creation was started.
	 */
	public String getContentTime()
	{
		Object objValue = getValue(0x0008, 0x0033);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * This method is used to set Image identification characteristics.
	 * The function accepts a String Value and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param arrStrImageType : Image identification characteristics.
	 */	
	public void setImageType(String[] arrStrImageType)
	{
		/*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(0x0008, 0x0008, DicomConstants.DCM_DT_CS, arrStrImageType);
	}
	/**
	 * Returns Image identification characteristics.
	 * 
	 * @return String[] - String value of Image type.
	 */
	public String[] getImageType()
	{
		Object objectValue = getValue(0x0008, 0x0008);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}
	/*
	 * Samples per Pixel (0028,0002) is the number of separate planes in the image. One, three, and
	 * four image planes are defined. For monochrome (gray scale) and palette color images, the number of planes is 1. For RGB and
	 * other three vector color models, the value of this attribute is 3. For four vector color models, the
	 * value of this attribute is 4.
	 * 
	 * @param enumSamplesPerPixel Number of samples (planes) in this image.
	 */
	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());
	}
	/**
	 * Return the number of separate planes in the image.
	 * 
	 * @return short - Short value of Samples Per Pixel.
	 */
	public short getSamplesPerPixel()
	{
		Object objectValue = getValue(0x0028, 0x0002);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	/**
	 * The method is used to set Specifies the intended interpretation of the pixel data.
	 * The function accepts a String Value and creates the
	 * DE based on the transfer syntax and populates the DE with right values.
	 * This De is then added to the Module HashMap
	 * 
	 * @param enumPhotometricInterpretation : Enum value of Photometric Interpretation
	 */
	public void setPhotometricInterpretation(EnumPhotometricInterpretation enumPhotometricInterpretation)
	{
		/*Accept Specifies the intended interpretation of the pixel data 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_CS, enumPhotometricInterpretation.getValue());
	}	
	/**
	 * Return the intended interpretation of the pixel data.
	 * 
	 * @return String - String value of Photometric Interpretation.
	 */
	public String getPhotometricInterpretation()
	{
		Object objectValue = getValue(0x0028, 0x0004);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	/**
	 * Sets Data representation of pixel samples.
	 * @param enumPixelRepresentation : Enum value of PixelRepresentation
	 */
	public void setPixelRepresentation(EnumPixelRepresentation enumPixelRepresentation)
	{
		/*Accept Pixel Representation in String 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());
	}	
	/**
	 * Returns Data representation of pixel samples.
	 * @return String - String value of PixelRepresentation
	 */
	public String getPixelRepresentation()
	{
		Object objectValue = getValue(0x0028, 0x0103);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}	
	/**
	 * Get the Instance of Basic Pixel Spacing Calibration Macro Attributes .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 Basic Pixel Spacing Calibration Macro Attributes which the user programmer can populate
	 */
	public BasicPixelSpacingCalibrationMacro getBasicPixelSpacingCalibrationMacro()
	{
		if(objBasicPixelSpacingCalibrationMacro == null)
			objBasicPixelSpacingCalibrationMacro = new BasicPixelSpacingCalibrationMacro(objIDataSet);
		return objBasicPixelSpacingCalibrationMacro; 
	}
	/**
	 * Sets Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size.
	 * @param strPixelAspectRatio String Value OF Pixel Aspect Ratio
	 */
	public void setPixelAspectRatio(String strPixelAspectRatio)
	{
		/*Accept the Pixel Aspect Ratio 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, 0x0034, DicomConstants.DCM_DT_IS,strPixelAspectRatio);
	}

	/**
	 * Retrieves Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the verticalpixel size, and the second value is the horizontal pixel size.
	 * @return String Array -  Value component of Pixel Aspect Ratio
	 */
	public String[] getPixelAspectRatio()
	{
		Object objValue = objIDataSet.getValue(0x0020, 0x0034);
		if(objValue != null)
			return (String[])objValue;
		return null;
	}
	/**
	 * Number of bits allocated for each pixel sample. Each sample shall have the same
	 * number of bits allocated.
	 * 
	 * @param enumBitsAllocated Enum value of 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());
	}
	/**
	 * Return Number of bits allocated for each pixel sample.
	 * 
	 * @return short - Short value of Bits Allocated.
	 */
	public short getBitsAllocated()
	{
		Object objectValue = getValue(0x0028, 0x0100);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	
	/**
	 * Number of bits stored for each pixel sample. Each sample shall have the same
	 * number of bits stored.
	 * 
	 * @param enumBitsStored Enum value of 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());
	}
	/**
	 * Number of bits stored for each pixel sample.
	 * 
	 * @return short - short value of Bits Stored.
	 */
	public short getBitsStored()
	{
		Object objectValue = getValue(0x0028, 0x0101);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}
	/**
	 * Most significant bit for pixel sample data. Each sample shall have the same high bit.
	 * 
	 * @param enumHighBit Enum 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());
	}
	/**
	 * Most significant bit for pixel sample data.
	 * 
	 * @return short - Short value of High Bit.
	 */
	public short getHighBit()
	{
		Object objectValue = getValue(0x0028, 0x0102);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Specifies whether an Image has undergone lossy compression.
	 * Enumerated Values: 00 = Image has NOT been subjected to lossy compression,
	 * 01 = Image has been subjected to lossy compression.
	 * 
	 * @param enumLossyImageCompression Enum value of Lossy Image Compression.
	 */
	public void setLossyImageCompression(EnumLossyImageCompression enumLossyImageCompression)
	{
		/*Accept Specifies whether an Image has undergone lossy compression.
		 * 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(0x0028, 0x2110, DicomConstants.DCM_DT_CS, enumLossyImageCompression.getValue());
	}
	/**
	 * Return whether an Image has undergone lossy compression.
	 * 
	 * @return String - String value of Lossy Image Compression.
	 */
	public String getLossyImageCompression()
	{
		Object objectValue = getValue(0x0028, 0x2110);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}
	/**
	 * Sets the approximate lossy compression ratio(s) that have been applied to this image.
	 * @param strLossyImageCompressionRatio String value of Lossy ImageCompression Ratio
	 */
	public void setLossyImageCompressionRatio(String[] strLossyImageCompressionRatio)
	{
		/*Accept the Lossy ImageCompression Ratio 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_DS,strLossyImageCompressionRatio);
	}
	/**
	 * Retrieves the approximate lossy compression ratio(s) that have been applied to this image.
	 * @return String - value of Lossy ImageCompression Ratio
	 */
	public String[] getLossyImageCompressionRatio()
	{
		Object objValue = getValue(0x0028,0x2112);
		if(objValue != null)
			return (String[])objValue;
		return null;
	}
	
	/**
	 * Sets LossyImageCompressionMethod
	 * @param strLossyImageCompressionMethod String Value component of LossyImageCompressionMethod
	 */
	public void setLossyImageCompressionMethod(String strLossyImageCompressionMethod)
	{
		/*Accept the Numeric 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 Data Set
		 */
		addDataElement(0x0028, 0x2114, DicomConstants.DCM_DT_CS,strLossyImageCompressionMethod);
	}
	/**
	 * Retrieves Numeric Value component of LossyImageCompressionMethod
	 * @return String Array -  Value component of LossyImageCompressionMethod
	 */
	public String[] getLossyImageCompressionMethod()
	{
		Object objectValue = getValue(0x0028,0x2114);
		if(objectValue!=null)
			return (String[])objectValue;
		return null;
	}
	/**
	 * Sets Indicates whether or not the encapsulated document contains sufficient burned in annotation to identify the patient and date the data was acquired.
	 * @param enumBurnedInAnnotation enum value of BurnedInAnnotation
	 */
	public void setBurnedInAnnotation(EnumBurnedInAnnotation enumBurnedInAnnotation)
	{
		/* Accept the BurnedInAnnotation 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_CS,enumBurnedInAnnotation);
	}
	/**
	 * Returns Indicates whether or not the encapsulated document contains sufficient burned in annotation to identify the patient and date the data was acquired.
	 * @return String - value of BurnedInAnnotation
	 */
	public String getBurnedInAnnotation()
	{
		Object objValue = getValue(0x0028,0x0301);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Sets Recognizable Visual Features
	 * @param enumRecognizableVisualFeatures enum value of RecognizableVisualFeatures
	 */
	public void setRecognizableVisualFeatures(EnumRecognizableVisualFeatures enumBurnedInAnnotation)
	{
		/* Accept the RecognizableVisualFeatures 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_CS,enumBurnedInAnnotation);
	}
	/**
	 * Returns Recognizable Visual Features
	 * @return String - value of RecognizableVisualFeatures
	 */
	public String getRecognizableVisualFeatures()
	{
		Object objValue = getValue(0x0028,0x0302);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	
	/**
	 * Sets Image Laterality
	 * @param enumImageLaterality enum value of ImageLaterality
	 */
	public void setImageLaterality(EnumImageLaterality enumImageLaterality)
	{
		/* Accept the ImageLaterality 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(0x0020,0x0062, DicomConstants.DCM_DT_CS,enumImageLaterality);
	}
	/**
	 * Returns Image Laterality
	 * @return String - value of ImageLaterality
	 */
	public String getImageLaterality()
	{
		Object objValue = getValue(0x0020,0x0062);
		if(objValue != null)
			return objValue.toString();
		return null;
	}
	/**
	 * Get the Instance of RealWorldValueMappingMacroAttributes .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 RealWorldValueMappingMacro Attributes which the user programmer can populate
	 */
	public RealWorldValueMappingMacro getRealWorldValueMappingMacro()
	{
		if(objRealWorldValueMappingMacro == null)
			objRealWorldValueMappingMacro = new RealWorldValueMappingMacro(objIDataSet);
		return objRealWorldValueMappingMacro; 
	}
	
	/**
	 * Get the Instance of General Anatomy Mandatory 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 General Anatomy Mandatory Macro which the user programmer can populate
	 */
	public GeneralAnatomyMandatoryMacro getGeneralAnatomyMandatoryMacro()
	{
		if(objGeneralAnatomyMandatoryMacro == null)
			objGeneralAnatomyMandatoryMacro = new GeneralAnatomyMandatoryMacro(objIDataSet);
		return objGeneralAnatomyMandatoryMacro; 
	}	
	/**
	 * 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;
	}
}
