/*******************************************************************************
 *  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.baselibs;



import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryReader;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IItem;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSourceMovementType;
import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidItemException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ValidationException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;

import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;


/**
* This item class contains the methods to set, get and validate the attribute present in Recorded Channel Sequence Item.
 */
public class RecordedChannelSequenceItem extends Item  
{
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * This constructor creates the item and internal code sequence macro with default TransferSyntax 
	 */
	RecordedChannelSequenceItem()
	{
		super();
	}

	/**
	 * This constructor creates the item and internal code sequence macro with default TransferSyntax 
	 * and default DictionaryReader
	 * @param objITransferSyntax specifies the DICOM Standard defined TransfeSyntax
	 */
	RecordedChannelSequenceItem(ITransferSyntax objITransferSyntax)
	{
		super(objITransferSyntax);
	}

	/**
	 * This constructor creates Recorded Channel Sequence Item with specified TransferSyntax and
	 * specified DictionaryReader
	 * @param objTransferSyntax specifies the DICOM Standard defined TransfeSyntax
	 * @param objDictionaryReader specifies the DICOM Dictionary reader to be used 
	 */
	RecordedChannelSequenceItem(ITransferSyntax objTransferSyntax, IDictionaryReader objDictionaryReader)
	{
		super(objTransferSyntax,objDictionaryReader);
	}

	/**
	 * Sets Identification number of the Channel. The value of Channel Number (300A,0282) shall be unique within the Application
	 * @param strChannelNumber String value of Channel Number.
	 */
	public void setChannelNumber(String strChannelNumber)
	{
		/* Accept the Channel Number 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0282,strChannelNumber,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0282,DicomConstants.DCM_DT_IS, strChannelNumber);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Identification number of the Channel. 
	 * @return String - value of Identification number of the Channel. 
	 */
	public String getChannelNumber()
	{
		Object objValue = getValue(0x300A,0x0282);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Length of Channel (mm).
	 * @param strChannelLength String value of Channel Length.
	 */
	public void setChannelLength(String strChannelLength)
	{
		/* Accept the Channel Length 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0284,strChannelLength,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0284,DicomConstants.DCM_DT_DS, strChannelLength);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Length of Channel (mm).
	 * @return String - value of Channel Length. 
	 */
	public String getChannelLength()
	{
		Object objValue = getValue(0x300A,0x0284);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Total amount of time specified between Control Point 0 and 
	 * final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec).
	 * @param strSpecifiedChannelTotalTime String value of Specified Channel Total Time.
	 */
	public void setSpecifiedChannelTotalTime(String strSpecifiedChannelTotalTime)
	{
		/* Accept the Specified Channel Total Time 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0132,strSpecifiedChannelTotalTime,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0132,DicomConstants.DCM_DT_DS, strSpecifiedChannelTotalTime);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Total amount of time specified between Control Point 0 and 
	 * final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec).
	 * @return String - value of Specified Channel Total Time.
	 */
	public String getSpecifiedChannelTotalTime()
	{
		Object objValue = getValue(0x3008,0x0132);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Total amount of time actually delivered between Control Point 0 and 
	 * final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec).
	 * @param strDeliveredChannelTotalTime String value of Delivered Channel Total Time.
	 */
	public void setDeliveredChannelTotalTime(String strDeliveredChannelTotalTime)
	{
		/* Accept the Delivered Channel Total Time 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x3008,0x0134,strDeliveredChannelTotalTime,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0134,DicomConstants.DCM_DT_DS, strDeliveredChannelTotalTime);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Total amount of time Delivered between Control Point 0 and 
	 * final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec).
	 * @return String - value of Delivered Channel Total Time.
	 */
	public String getDeliveredChannelTotalTime()
	{
		Object objValue = getValue(0x3008,0x0134);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Type of Source movement.
	 * Defined Terms: STEPWISE, FIXED, OSCILLATING, UNIDIRECTIONAL.
	 * @param enumSourceMovementType Enum value of Type of Source movement.
	 */
	public void setSourceMovementType(EnumSourceMovementType enumSourceMovementType)
	{
		/* Accept the Source Movement Type 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x300A,0x0288,enumSourceMovementType.getValue(),getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0288,DicomConstants.DCM_DT_CS, enumSourceMovementType.getValue());

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Type of Source movement.
	 * @return String - value of Source Movement Type.
	 */
	public String getSourceMovementType()
	{
		Object objValue = getValue(0x300A,0x0288);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Number of Pulses specified per fraction for current Channel.
	 * @param strSpecifiedNumberOfPulses String value of Specified Number of Pulses.
	 */
	public void setSpecifiedNumberOfPulses(String strSpecifiedNumberOfPulses)
	{
		/* Accept the Specified Number of Pulses 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0136,strSpecifiedNumberOfPulses,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0136,DicomConstants.DCM_DT_IS, strSpecifiedNumberOfPulses);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Number of Pulses specified per fraction for current Channel.
	 * @return String - value of Specified Number of Pulses.
	 */
	public String getSpecifiedNumberOfPulses()
	{
		Object objValue = getValue(0x3008,0x0136);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Number of Pulses actually delivered per fraction for current Channel.
	 * @param strDeliveredNumberOfPulses String value of Delivered Number of Pulses.
	 */
	public void setDeliveredNumberOfPulses(String strDeliveredNumberOfPulses)
	{
		/* Accept the Delivered Number of Pulses 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0138,strDeliveredNumberOfPulses,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0138,DicomConstants.DCM_DT_IS, strDeliveredNumberOfPulses);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Number of Pulses delivered per fraction for current Channel.
	 * @return String - value of Delivered Number of Pulses.
	 */
	public String getDeliveredNumberOfPulses()
	{
		Object objValue = getValue(0x3008,0x0138);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Pulse repetition interval (sec) specified for current Channel.
	 * @param strSpecifiedPulseRepetitionInterval String value of Specified Pulse Repetition Interval.
	 */
	public void setSpecifiedPulseRepetitionInterval(String strSpecifiedPulseRepetitionInterval)
	{
		/* Accept the Specified Pulse Repetition Interval 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x013A,strSpecifiedPulseRepetitionInterval,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x013A,DicomConstants.DCM_DT_DS, strSpecifiedPulseRepetitionInterval);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Pulse repetition interval (sec) specified for current Channel.
	 * @return String - value of Specified Pulse Repetition Interval.
	 */
	public String getSpecifiedPulseRepetitionInterval()
	{
		Object objValue = getValue(0x3008,0x013A);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Pulse repetition interval (sec) actually delivered for current Channel.
	 * @param strDeliveredPulseRepetitionInterval String value of Delivered Pulse Repetition Interval.
	 */
	public void setDeliveredPulseRepetitionInterval(String strDeliveredPulseRepetitionInterval)
	{
		/* Accept the Delivered Pulse Repetition Interval 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x013C,strDeliveredPulseRepetitionInterval,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x013C,DicomConstants.DCM_DT_DS, strDeliveredPulseRepetitionInterval);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Pulse repetition interval (sec) Delivered for current Channel.
	 * @return String - value of Delivered Pulse Repetition Interval.
	 */
	public String getDeliveredPulseRepetitionInterval()
	{
		Object objValue = getValue(0x3008,0x013C);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Retrieves pre-initialized object of Referenced Measured Dose Reference 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
	 * @return ReferencedMeasuredDoseReferenceSequence - instance of Referenced Measured Dose Reference Sequence. 
	 */
	public ReferencedMeasuredDoseReferenceSequence getReferencedMeasuredDoseReferenceSequence()
	{
		ReferencedMeasuredDoseReferenceSequence objReferencedMeasuredDoseReferenceSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0080);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objReferencedMeasuredDoseReferenceSequence = (ReferencedMeasuredDoseReferenceSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objReferencedMeasuredDoseReferenceSequence = (ReferencedMeasuredDoseReferenceSequence)objDicomV3Factory.createSequence(0x3008,0x0080, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0080, objReferencedMeasuredDoseReferenceSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0080, DicomConstants.DCM_DT_SQ, objReferencedMeasuredDoseReferenceSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objReferencedMeasuredDoseReferenceSequence;
	}

	/**
	 * Retrieves pre-initialized object of Referenced Calculated Dose Reference 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
	 * @return ReferencedCalculatedDoseReferenceSequence - instance of Referenced Calculated Dose Reference Sequence. 
	 */
	public ReferencedCalculatedDoseReferenceSequence getReferencedCalculatedDoseReferenceSequence()
	{
		ReferencedCalculatedDoseReferenceSequence objReferencedCalculatedDoseReferenceSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0090);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objReferencedCalculatedDoseReferenceSequence = (ReferencedCalculatedDoseReferenceSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objReferencedCalculatedDoseReferenceSequence = (ReferencedCalculatedDoseReferenceSequence)objDicomV3Factory.createSequence(0x3008,0x0090, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0090, objReferencedCalculatedDoseReferenceSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0090, DicomConstants.DCM_DT_SQ, objReferencedCalculatedDoseReferenceSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objReferencedCalculatedDoseReferenceSequence;
	}

	/**
	 * Retrieves pre-initialized object of Recorded Source Applicator 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
	 * @return RecordedSourceApplicatorSequence - instance of Recorded Source Applicator Sequence. 
	 */
	public RecordedSourceApplicatorSequence getRecordedSourceApplicatorSequence()
	{
		RecordedSourceApplicatorSequence objRecordedSourceApplicatorSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0140);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objRecordedSourceApplicatorSequence = (RecordedSourceApplicatorSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objRecordedSourceApplicatorSequence = (RecordedSourceApplicatorSequence)objDicomV3Factory.createSequence(0x3008,0x0140, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0140, objRecordedSourceApplicatorSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0140, DicomConstants.DCM_DT_SQ, objRecordedSourceApplicatorSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objRecordedSourceApplicatorSequence;
	}

	/**
	 * Sets Identification number of the Transfer Tube.
	 * @param strTransferTubeNumber String value of Transfer Tube Number.
	 */
	public void setTransferTubeNumber(String strTransferTubeNumber)
	{
		/* Accept the Transfer Tube Number 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x02A2,strTransferTubeNumber,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x02A2,DicomConstants.DCM_DT_IS, strTransferTubeNumber);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Identification number of the Transfer Tube.
	 * @return String - value of Transfer Tube Number.
	 */
	public String getTransferTubeNumber()
	{
		Object objValue = getValue(0x300A,0x02A2);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Length of Transfer Tube of current afterloading Channel (mm).
	 * @param strTransferTubeLength String value of Transfer Tube Length.
	 */
	public void setTransferTubeLength(String strTransferTubeLength)
	{
		/* Accept the Transfer Tube Length 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x02A4,strTransferTubeLength,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x02A4,DicomConstants.DCM_DT_DS, strTransferTubeLength);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Length of Transfer Tube of current afterloading Channel (mm).
	 * @return String - value of Transfer Tube Length.
	 */
	public String getTransferTubeLength()
	{
		Object objValue = getValue(0x300A,0x02A4);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Retrieves pre-initialized object of Recorded Channel Shield 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
	 * @return RecordedChannelShieldSequence - instance of Recorded Channel Shield Sequence. 
	 */
	public RecordedChannelShieldSequence getRecordedChannelShieldSequence()
	{
		RecordedChannelShieldSequence objRecordedChannelShieldSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0150);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objRecordedChannelShieldSequence = (RecordedChannelShieldSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objRecordedChannelShieldSequence = (RecordedChannelShieldSequence)objDicomV3Factory.createSequence(0x3008,0x0150, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0150, objRecordedChannelShieldSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0150, DicomConstants.DCM_DT_SQ, objRecordedChannelShieldSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objRecordedChannelShieldSequence;
	}

	/**
	 * Uniquely identifies the referenced Source within the Recorded Source Sequence (3008,0100) for current Application Setup.
	 * @param strReferencedSourceNumber String value of Referenced Source Number.
	 */
	public void setReferencedSourceNumber(String strReferencedSourceNumber)
	{
		/* Accept the Referenced Source Number 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300C,0x000E,strReferencedSourceNumber,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300C,0x000E,DicomConstants.DCM_DT_IS, strReferencedSourceNumber);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves referenced Source within the Recorded Source Sequence (3008,0100) for current Application Setup.
	 * @return String - value of Referenced Source Number.
	 */
	public String getReferencedSourceNumber()
	{
		Object objValue = getValue(0x300C,0x000E);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Date on which the source(s) exited the safe.
	 * @param strSafePositionExitDate String value of Safe Position Exit Date.
	 */
	public void setSafePositionExitDate(String strSafePositionExitDate)
	{
		/* Accept the Safe Position Exit 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0162,strSafePositionExitDate,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0162,DicomConstants.DCM_DT_DA, strSafePositionExitDate);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Date on which the source(s) exited the safe.
	 * @return String - value of Safe Position Exit Date.
	 */
	public String getSafePositionExitDate()
	{
		Object objValue = getValue(0x3008,0x0162);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Time on which the source(s) exited the safe.
	 * @param strSafePositionExitDate String value of Safe Position Exit Time.
	 */
	public void setSafePositionExitTime(String strSafePositionExitDate)
	{
		/* Accept the Safe Position Exit 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0164,strSafePositionExitDate,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0164,DicomConstants.DCM_DT_TM, strSafePositionExitDate);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Time on which the source(s) exited the safe.
	 * @return String - value of Safe Position Exit Time.
	 */
	public String getSafePositionExitTime()
	{
		Object objValue = getValue(0x3008,0x0164);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Date on which the source(s) returned to the safe.
	 * @param strSafePositionReturnDate String value of Safe Position Return Date.
	 */
	public void setSafePositionReturnDate(String strSafePositionReturnDate)
	{
		/* Accept the Safe Position Return 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x3008,0x0166,strSafePositionReturnDate,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0166,DicomConstants.DCM_DT_DA, strSafePositionReturnDate);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Date on which the source(s) returned to the safe.
	 * @return String - value of Safe Position Return Date.
	 */
	public String getSafePositionReturnDate()
	{
		Object objValue = getValue(0x3008,0x0166);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Time on which the source(s) returned to the safe.
	 * @param strSafePositionReturnTime String value of Safe Position Return Time.
	 */
	public void setSafePositionReturnTime(String strSafePositionReturnTime)
	{
		/* Accept the Safe Position Return 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)	
			objIDataElement = new ImplicitDE(0x3008,0x0168,strSafePositionReturnTime,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x3008,0x0168,DicomConstants.DCM_DT_TM, strSafePositionReturnTime);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Time on which the source(s) returned to the safe.
	 * @return String - value of Safe Position Return Time.
	 */
	public String getSafePositionReturnTime()
	{
		Object objValue = getValue(0x3008,0x0168);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Sets Number of control points in Channel.For an N-segment Channel there will be 2N or N+1 control points.
	 * @param strNumberOfControlPoints String value of Number of Control Points.
	 */
	public void setNumberOfControlPoints(String strNumberOfControlPoints)
	{
		/* Accept the Number of Control Points 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
		 */
		IDataElement objIDataElement = null;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(0x300A,0x0110,strNumberOfControlPoints,getDictionaryReader());
		else
			objIDataElement = new ExplicitDE(0x300A,0x0110,DicomConstants.DCM_DT_IS, strNumberOfControlPoints);

		addDataElement(objIDataElement);
	}

	/**
	 * Retrieves Number of control points in Channel.
	 * @return String - value of Number of control points in Channel.
	 */
	public String getNumberOfControlPoints()
	{
		Object objValue = getValue(0x300A,0x0110);
		if(objValue != null)
			return objValue.toString();
		return null;
	}

	/**
	 * Retrieves pre-initialized object of Brachy Control Point Delivered 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
	 * @return BrachyControlPointDeliveredSequence - instance of Brachy Control Point Delivered Sequence. 
	 */
	public BrachyControlPointDeliveredSequence getBrachyControlPointDeliveredSequence()
	{
		BrachyControlPointDeliveredSequence objBrachyControlPointDeliveredSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0160);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objBrachyControlPointDeliveredSequence = (BrachyControlPointDeliveredSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objBrachyControlPointDeliveredSequence = (BrachyControlPointDeliveredSequence)objDicomV3Factory.createSequence(0x3008,0x0160, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0160, objBrachyControlPointDeliveredSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0160, DicomConstants.DCM_DT_SQ, objBrachyControlPointDeliveredSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objBrachyControlPointDeliveredSequence;
	}
	
	/**
	 * Retrieves pre-initialized object of Pulse Specific Brachy Control Point Delivered 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
	 * @return PulseSpecificBrachyControlPointDeliveredSequence - instance of Pulse Specific Brachy Control Point Delivered Sequence. 
	 */
	public PulseSpecificBrachyControlPointDeliveredSequence getPulseSpecificBrachyControlPointDeliveredSequence()
	{
		PulseSpecificBrachyControlPointDeliveredSequence objPulseSpecificBrachyControlPointDeliveredSequence = null;
		IDataElement objIDataElement =  getDataForTag(0x3008,0x0171);
		if(objIDataElement != null)
		{
			IDicomValue objIDicomValue = objIDataElement.getDicomValue();
			if(objIDicomValue != null)
				objPulseSpecificBrachyControlPointDeliveredSequence = (PulseSpecificBrachyControlPointDeliveredSequence)objIDicomValue;
		}
		else
		{
			DicomV3Factory objDicomV3Factory = DicomV3Factory.createInstance();
			int iVRTransferSyntax = objITransferSyntax.getVRTransferSyntax();
			objIDataElement = null;
			objPulseSpecificBrachyControlPointDeliveredSequence = (PulseSpecificBrachyControlPointDeliveredSequence)objDicomV3Factory.createSequence(0x3008,0x0160, objITransferSyntax, objIDictionaryReader);

			if(iVRTransferSyntax == DicomConstants.DCM_VR_IMPLICIT)
				objIDataElement = new ImplicitDE(0x3008,0x0171, objPulseSpecificBrachyControlPointDeliveredSequence.getValue(),objIDictionaryReader);
			else
				objIDataElement = new ExplicitDE(0x3008,0x0171, DicomConstants.DCM_DT_SQ, objPulseSpecificBrachyControlPointDeliveredSequence.getValue());
			objIDataElement.setTransferSyntax(objITransferSyntax);
			if(objIDataElement != null)
				addDataElement(objIDataElement);
		}
		return objPulseSpecificBrachyControlPointDeliveredSequence;
	}


	/**
	 * Validates all the attributes in {@link RecordedChannelSequenceItem} that are present in the DataSet.
	 * @return boolean - Success -true, Failure - false.
	 * @throws InvalidItemException throws InvalidItemException If Mandatory or Conditional element fails.
	 */
	public boolean validateForModule()  throws InvalidItemException
	{
		try{
			if(!contains(0x300A,0x0282))
				throw new MandatoryMissingException("300A,0282");
			if(!contains(0x300A,0x0284))
				throw new MandatoryMissingException("300A,0284");
			if(!contains(0x3008,0x0132))
				throw new MandatoryMissingException("3008,0132");
			if(!contains(0x3008,0x0134))
				throw new MandatoryMissingException("3008,0134");
			if(!contains(0x300A,0x0288))
				throw new MandatoryMissingException("300A,0288");
			if(!contains(0x300A,0x02A2))
				throw new MandatoryMissingException("300A,02A2");
			if(!contains(0x300C,0x000E))
				throw new MandatoryMissingException("300C,000E");
			if(!contains(0x300A,0x0110))
				throw new MandatoryMissingException("300A,0110");
			if(!contains(0x3008,0x0160))
				throw new MandatoryMissingException("3008,0160");
			/*
			 * The following conditions are dependent upon module. Thus validation for following attributes are done at module level.
			 * 3008,0136 Specified Number of Pulses. Required if Brachy Treatment Type (300A,0202) is PDR.
			 * 3008,0138 Delivered Number of Pulses. Required if Brachy Treatment Type (300A,0202) is PDR.
			 * 3008,013A Specified Pulse Repetition Interval .Required if Brachy Treatment Type (300A,0202) is PDR.
			 * 3008,013C Delivered Pulse Repetition Interval. Required if Brachy Treatment Type (300A,0202) is PDR.
			 * 3008,0162 Safe Position Exit Date. Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL.
			 * 3008,0166 Safe Position Return Date.Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL.
			 * 3008,0168 Safe Position Return Time.Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL.
			 */
			String strTransferTubeNumber = getTransferTubeNumber();
			if(strTransferTubeNumber != null)
			{
				if(strTransferTubeNumber.length() != 0 && !contains(0x300A,0x02A4))
					throw new ConditionFailedException("300A,02A4 Required if value Transfer Tube Number (300A,02A2) is not zero length.");
			}

			/*
			 * This condition is to validate  RecordedSourceApplicatorSequence. As the attribute of this sequence is depenedent on attribute of 
			 * Recorded Channel Sequence. Thus validation is done here.
			 * Please refer p.d.f Chapter 3 page No. 528 .
			 * 300A,02A0 Source Applicator Step Size.
			 */
			String strSourceMovementType = getSourceMovementType();
			if(strSourceMovementType != null && strSourceMovementType.equalsIgnoreCase(EnumSourceMovementType.STEPWISE.getValue()))
			{
				RecordedSourceApplicatorSequence objRecordedSourceApplicatorSequence = getRecordedSourceApplicatorSequence();
				RecordedSourceApplicatorSequenceItem objRecordedSourceApplicatorSequenceItem = null;
				ICollectionIterator<IItem> objRecordedSourceApplicatorSequenceIterator = objRecordedSourceApplicatorSequence.iterator();
				while(objRecordedSourceApplicatorSequenceIterator.hasNext())
				{
					objRecordedSourceApplicatorSequenceItem = (RecordedSourceApplicatorSequenceItem)objRecordedSourceApplicatorSequenceIterator.next();
					if(!objRecordedSourceApplicatorSequenceItem.contains(0x300A,0x02A0))
						throw new ConditionFailedException("300A,02A0 Required if Source Movement Type (300A,0288) is STEPWISE.");
				}
			}
		}
		catch(ConditionFailedException cfe)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(cfe.getMessage());
			}
			throw new ValidationException(this.getClass().getSimpleName(),cfe);
		}
		catch( MandatoryMissingException me)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(me.getMessage());
			}
			throw new ValidationException(this.getClass().getSimpleName(),me);
		}
		return true;
	}
}
