/*******************************************************************************
 *  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.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.enums.EnumImageType;

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.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

// TODO: Auto-generated Javadoc
/**
 \* This module specifies the Attributes of a NM Multi-frame Image. This module is always included in
 * a NM SOP instance, even if there is only one frame in the image.
 * 
 * 
 */
public class NMMultiFrameModule extends Module  
{


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


	/**
	 * Instantiates a new nM multi frame module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public NMMultiFrameModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0028,0x0009));
		objSingleCollection.add(new Tag(0x0054,0x0010));
		objSingleCollection.add(new Tag(0x0054,0x0011));
		objSingleCollection.add(new Tag(0x0054,0x0020));
		objSingleCollection.add(new Tag(0x0054,0x0021));
		objSingleCollection.add(new Tag(0x0054,0x0030));
		objSingleCollection.add(new Tag(0x0054,0x0031));
		objSingleCollection.add(new Tag(0x0054,0x0050));
		objSingleCollection.add(new Tag(0x0054,0x0051));
		objSingleCollection.add(new Tag(0x0054,0x0060));
		objSingleCollection.add(new Tag(0x0054,0x0061));
		objSingleCollection.add(new Tag(0x0054,0x0070));
		objSingleCollection.add(new Tag(0x0054,0x0071));
		objSingleCollection.add(new Tag(0x0054,0x0080));
		objSingleCollection.add(new Tag(0x0054,0x0081));
		objSingleCollection.add(new Tag(0x0054,0x0090));
		objSingleCollection.add(new Tag(0x0054,0x0100));
	}

	/**
	 * 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(0x0028,0x0009))
			throw new MandatoryMissingException("Missing Mandatory Element 0028,0009");
		else if(!isPresent(0x0054,0x0011))
			throw new MandatoryMissingException("Missing Mandatory Element 0054,0011");
		else if(!isPresent(0x0054,0x0021))
			throw new MandatoryMissingException("Missing Mandatory Element 0054,0021");
		else
		{
			/*
			 * Check conditions for type 1C and 2C type attributes. All these attributes if present in the module,
			 * then it should also be present in the Frame Increment Pointer(0x0028, 0x0009) value.
			 * We use the isTagPresent method of this module to check this condition.
			 */
			ISingleCollection<ITag> objISingleCollection = getFrameIncrementPointer();
			if(objISingleCollection != null )
			{
				if(isTagPresent(objISingleCollection, 0x0054, 0x0010) && !(isPresent(0x0054, 0x0010)))
					throw new ConditionFailedException("0054, 0010 Required if Frame Increment Pointer (0028,0009) includes the Tag for Energy Window Vector (0054,0010).");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0020) && !(isPresent(0x0054, 0x0020)))
					throw new ConditionFailedException("0054, 0020 Required if Frame Increment Pointer (0028,0009) includes the Tag for Detector Vector (0054,0020).");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0030) && !(isPresent(0x0054, 0x0030)))
					throw new ConditionFailedException("0054, 0030 Required if Frame Increment Pointer (0028,0009) includes the Tag for Phase Vector (0054,0030).");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0030) && !(isPresent(0x0054, 0x0031)))
					throw new ConditionFailedException("0054, 0031 Required if Frame Increment Pointer (0028,0009) includes the Tag for Phase Vector (0054,0030).");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0050) && !(isPresent(0x0054, 0x0050)))
					throw new ConditionFailedException("0054, 0050 Required if Frame Increment Pointer (0028,0009) includes the Tag for Rotation Vector 0054, 0050");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0060)&& !(isPresent(0x0054, 0x0060)))
					throw new ConditionFailedException("0054, 0060 Required if Frame Increment Pointer (0028,0009) includes the Tag for R-R Interval Vector 0054, 0060");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0060) && !(isPresent(0x0054, 0x0061)))
					throw new ConditionFailedException("0054, 0061 Required if Frame Increment Pointer (0028,0009) includes the Tag for R-R Interval Vector 0054, 0060");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0070) && !(isPresent(0x0054, 0x0070)))
					throw new ConditionFailedException("0054, 0070 Required if Frame Increment Pointer (0028,0009) includes the Tag for Time Slot Vector 0054, 0070");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0070) && !(isPresent(0x0054, 0x0071)))
					throw new ConditionFailedException("0054, 0071 Required if Frame Increment Pointer (0028,0009) includes the Tag for Time Slot Vector 0054, 0070");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0080)&& !(isPresent(0x0054, 0x0080)))
					throw new ConditionFailedException("0054, 0080 Required if Frame Increment Pointer (0028,0009) includes the Tag for Slice Vector 0054, 0080");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0080) && !(isPresent(0x0054, 0x0081)))
					throw new ConditionFailedException("0054, 0081 Required if Frame Increment Pointer (0028,0009) includes the Tag for Slice Vector 0054, 0080");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0090) && !(isPresent(0x0054, 0x0090)))
					throw new ConditionFailedException("0054, 0090 Required if Frame Increment Pointer (0028,0009) includes the Tag for Angular View Vector 0054, 0090 ");
				else if(isTagPresent(objISingleCollection, 0x0054, 0x0100)&& !(isPresent(0x0054, 0x0100)))
					throw new ConditionFailedException("0054, 0100 Required if Frame Increment Pointer (0028,0009) includes the Tag for Time Slice Vector 0054, 0100");
			}
			if(isPresent(0x0008, 0x0008))
			{
				/*
				 * Number of rotations (0x0054, 0x0051) is required if Image Type (0008,0008), Value 3 is
				 * TOMO,GATED TOMO,RECON TOMO, or RECON GATED TOMO.
				 */
				NMImageModule objNMImageModule=new NMImageModule(objIDataSet);
				String[] strImageType = objNMImageModule.getImageType();
				String strValueThree = strImageType[2];

				if(strValueThree != null)
				{
					if((strValueThree.equalsIgnoreCase(EnumImageType.Value3.TOMO.getValue()) ||strValueThree.equalsIgnoreCase(EnumImageType.Value3.GATED_TOMO.getValue()) ||
							strValueThree.equalsIgnoreCase(EnumImageType.Value3.RECON_TOMO.getValue()) || strValueThree.equalsIgnoreCase(EnumImageType.Value3.RECON_GATED_TOMO.getValue())) && (!isPresent(0x0054, 0x0051)))
						throw new ConditionFailedException("Condition Failed for Element 0054, 0051");
				}
			}
		}
		}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;
	}

	/*
	 * Modified for using custom collection instead of vector
	 * This method checks if the DataElement for the specified GroupNumber and ElementNumber is present
	 * in the FrameIncrementPointer (0028,0009) value.
	 */
	/**
	 * Checks if is tag present.
	 * 
	 * @param objISingleCollection the obj i single collection
	 * @param iGroupNumber the i group number
	 * @param iElementNumber the i element number
	 * 
	 * @return true, if is tag present
	 */
	@SuppressWarnings("unchecked")
	private static boolean isTagPresent(ISingleCollection objISingleCollection, int iGroupNumber, int iElementNumber)
	{
		ICollectionIterator<ITag> objICollectionIterator = objISingleCollection.iterator();
		while(objICollectionIterator.hasNext())
		{
			ITag objITag = new Tag(iGroupNumber,iElementNumber);
			if(objISingleCollection.contains(objITag))
				return true;
			objICollectionIterator.next();
		}
		return false;
	}

	/**
	 * Contains the Data Element Tags of one or more frame index vectors.
	 * 
	 * @param objSingleCollection - ISingleCollection of tags.
	 */
	/*
	 * This method is given since the user can specify multiple GroupNumber and ElementNumbers
	 */
	public void setFrameIncrementPointer(ISingleCollection<ITag> objSingleCollection)
	{
		/*Accept Frame Increment Pointer in String format of type short array.
		 * 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, 0x0009, DicomConstants.DCM_DT_AT, objSingleCollection);
	}

	/**
	 * Sets An array which contains the energy window number for each frame.
	 * 
	 * @param arrShEnergyWindowVector - Short array which contains the energy window number for each frame.
	 */
	public void setEnergyWindowVector(short[] arrShEnergyWindowVector)
	{
		/*Accept Energy Window Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0010, DicomConstants.DCM_DT_US, arrShEnergyWindowVector);
	}

	/**
	 * Sets Number of energy window groupings.
	 * 
	 * @param shNumberofEnergyWindows - Short value of  Number of energy window groupings.
	 */
	public void setNumberofEnergyWindows(short shNumberofEnergyWindows)
	{
		/*Accept Number of Energy Windows in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0011, DicomConstants.DCM_DT_US, shNumberofEnergyWindows);
	}

	/**
	 * Sets An array which contains the detector number for each frame.
	 * 
	 * @param arrShDetectorVector - Short array which contains the detector number for each frame.
	 */
	public void setDetectorVector(short[] arrShDetectorVector)
	{
		/*Accept Detector Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0020, DicomConstants.DCM_DT_US, arrShDetectorVector);
	}

	/**
	 * Sets Number of detectors.
	 * 
	 * @param shNumberOfDetectors - Short value of Number of detectors.
	 */
	public void setNumberOfDetectors(short shNumberOfDetectors)
	{
		/*Accept Number Of Detectors in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0021, DicomConstants.DCM_DT_US, shNumberOfDetectors);
	}

	/**
	 * Sets An array which contains the phase number for each frame.
	 * 
	 * @param arrShPhaseVector - Short Array which contains the phase number for each frame.
	 */
	public void setPhaseVector(short[] arrShPhaseVector)
	{
		/*Accept Phase Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0030, DicomConstants.DCM_DT_US, arrShPhaseVector);
	}

	/**
	 * Sets Number of phases.
	 * 
	 * @param shNumberOfPhases - Short value of Number of phases.
	 */
	public void setNumberOfPhases(short shNumberOfPhases)
	{
		/*Accept Number Of Phases in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0031, DicomConstants.DCM_DT_US, shNumberOfPhases);
	}

	/**
	 * Sets An array which contains the rotation number for each frame.
	 * 
	 * @param arrShRotationVector - Short array which contains the rotation number for each frame.
	 */
	public void setRotationVector(short[] arrShRotationVector)
	{
		/*Accept Rotation Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0050, DicomConstants.DCM_DT_US, arrShRotationVector);
	}

	/**
	 * Sets Number of rotations.
	 * 
	 * @param shNumberOfRotations - Short value of Number of rotations .
	 */
	public void setNumberOfRotations(short shNumberOfRotations)
	{

		/*Accept Number Of Rotations in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0051, DicomConstants.DCM_DT_US, shNumberOfRotations);
	}

	/**
	 * Sets An array which contains the R-R interval number for each frame.
	 * 
	 * @param arrShRRIntervalVector - Short array of RRIntervalVector
	 */
	public void setRRIntervalVector(short[] arrShRRIntervalVector)
	{
		/*Accept R-R Interval Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0060, DicomConstants.DCM_DT_US, arrShRRIntervalVector);
	}

	/**
	 * Sets Number of R-R Intervals.
	 * 
	 * @param shNumberOfRRIntervals the sh number of rr intervals
	 */
	public void setNumberOfRRIntervals(short shNumberOfRRIntervals)
	{

		/*Accept Number Of R-R Intervals in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0061, DicomConstants.DCM_DT_US, shNumberOfRRIntervals);
	}

	/**
	 * Sets An array which contains the time slot number for each frame.
	 * 
	 * @param arrShTimeSlotVector - Short array of Time Slot Vector.
	 */
	public void setTimeSlotVector(short[] arrShTimeSlotVector)
	{
		/*Accept Time Slot Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0070, DicomConstants.DCM_DT_US, arrShTimeSlotVector);
	}

	/**
	 * Sets Number of Time Slots.
	 * 
	 * @param shNumberOfTimeSlots the sh number of time slots
	 */
	public void setNumberOfTimeSlots(short shNumberOfTimeSlots)
	{

		/*Accept Number Of R-R Time Slots in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0071, DicomConstants.DCM_DT_US, shNumberOfTimeSlots);
	}

	/**
	 * Sets An array which contains the spatial slice number for each frame.
	 * 
	 * @param arrShSliceVector - Short array of Slice Vector.
	 */
	public void setSliceVector(short[] arrShSliceVector)
	{
		/*Accept Slice Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0080, DicomConstants.DCM_DT_US, arrShSliceVector);
	}

	/**
	 * Sets Number of Slices.
	 * 
	 * @param shNumberOfTimeSlices - Short value of Number Of Time Slices.
	 */
	public void setNumberOfSlices(short shNumberOfTimeSlices)
	{

		/*Accept Number Of Slices in short  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 Hash Map
		 */
		addDataElement(0x0054, 0x0081, DicomConstants.DCM_DT_US, shNumberOfTimeSlices);
	}

	/**
	 * Sets An array which contains the angular view number for each frame.
	 * 
	 * @param arrShAngularViewVector - Short array of Angular View Vector.
	 */
	public void setAngularViewVector(short[] arrShAngularViewVector)
	{
		/*Accept Angular View Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0090, DicomConstants.DCM_DT_US, arrShAngularViewVector);
	}

	/**
	 * Sets An array which contains the time slice number for each frame.
	 * 
	 * @param arrShTimeSliceVector - Short array of Time Slice Vector.
	 */
	public void setTimeSliceVector(short[] arrShTimeSliceVector)
	{
		/*Accept Time Slice Vector in short array 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 Hash Map
		 */
		addDataElement(0x0054, 0x0100, DicomConstants.DCM_DT_US, arrShTimeSliceVector);
	}

	/**
	 * Retrieves Data Element Tags of one or more frame index vectors.
	 * 
	 * @return ISingleCollection - ISingleCollection of tags.
	 */
	@SuppressWarnings("unchecked")
	public ISingleCollection<ITag> getFrameIncrementPointer()
	{
		Object objValue = getValue(0x0028,0x0009);
		if(objValue != null)
			return (ISingleCollection<ITag>)objValue;
		return null;
	}

	/**
	 * Retrieves An array which contains the energy window number for each frame.
	 * 
	 * @return Short[] - Short array of Energy Window Vector.
	 */
	public short[] getEnergyWindowVector()
	{
		Object objectValue = getValue(0x0054, 0x0010);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of energy window groupings.
	 * 
	 * @return Short - Number of Energy Windows
	 */
	public short getNumberofEnergyWindows()
	{Object objectValue = getValue(0x0054, 0x0011);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves An array which contains the detector number for each frame.
	 * 
	 * @return Short[] - Short array of Detector Vector.
	 */
	public short[] getDetectorVector()
	{
		Object objectValue = getValue(0x0054, 0x0020);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of detectors.
	 * 
	 * @return Short - Short value of Number Of Detectors
	 */
	public short getNumberOfDetectors()
	{Object objectValue = getValue(0x0054, 0x0021);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves An array which contains the phase number for each frame.
	 * 
	 * @return short[] - Short array of Phase Vector.
	 */
	public short[] getPhaseVector()
	{
		Object objectValue = getValue(0x0054, 0x0030);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of phases.
	 * 
	 * @return short - Short array of Number of Phases.
	 */
	public short getNumberOfPhases()
	{Object objectValue = getValue(0x0054, 0x0031);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves  An array which contains the rotation number for each frame.
	 * 
	 * @return short[] - Short array of Rotation number for each frame.
	 */
	public short[] getRotationVector()
	{
		Object objectValue = getValue(0x0054, 0x0050);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of rotations.
	 * 
	 * @return short - Short value of Number Of Rotation.
	 */
	public short getNumberOfRotations()
	{Object objectValue = getValue(0x0054, 0x0051);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves R-R Interval Vector, array which contains the R-R interval number for each frame..
	 * 
	 * @return short[] - Short array which contains the R-R interval number for each frame.
	 */
	public short[] getRRIntervalVector()
	{
		Object objectValue = getValue(0x0054, 0x0060);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of R-R intervals.
	 * 
	 * @return short - Number of R-R intervals.
	 */
	public short getNumberOfRRIntervals()
	{Object objectValue = getValue(0x0054, 0x0061);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves An array which contains the time slot number for each frame.
	 * 
	 * @return short[] - Short array which contains the time slot number for each frame.
	 */
	public short[] getTimeSlotVector()
	{
		Object objectValue = getValue(0x0054, 0x0070);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of time slots.
	 * 
	 * @return short - Number of time slots.
	 */
	public short getNumberOfTimeSlots()
	{Object objectValue = getValue(0x0054, 0x0071);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves An array which contains the spatial slice number for each frame.
	 * 
	 * @return short[] - short array which contains the spatial slice number for each frame.
	 */
	public short[] getSliceVector()
	{
		Object objectValue = getValue(0x0054, 0x0080);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves Number of slices.
	 * 
	 * @return short - short value of Number of slices..
	 */
	public short getNumberOfSlices()
	{Object objectValue = getValue(0x0054, 0x0081);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * Retrieves An array which contains the angular view number for each frame.
	 * 
	 * @return short[] - Short array which contains the angular view number for each frame.
	 */
	public short[] getAngularViewVector()
	{
		Object objectValue = getValue(0x0054, 0x0090);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/**
	 * Retrieves An array which contains the time slice number for each frame.
	 * 
	 * @return short[] - Short array which contains the time slice number for each frame.
	 */
	public short[] getTimeSliceVector()
	{
		Object objectValue = getValue(0x0054, 0x0100);
		if(objectValue!=null)
			return (short[])objectValue;
		return null;
	}

	/* 
	 * I have modified the collection type from vector to custom class
	 * 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.
	 * Modified made access protected
	 */
	/**
	 * 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;
	}
}
