/*******************************************************************************
 *  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.
 *******************************************************************************/
/*
/**
 * 
 * This class specifies the Attributes necessary to uniquely identify a frame of reference which
insures the spatial relationship of Images within a Series. It also allows Images across multiple
Series to share the same Frame Of Reference. This Frame Of Reference (or coordinate system)
shall be constant for all Images related to a specific Frame Of Reference.
When a Frame of Reference is identified, it is not important how the Patient is positioned relative
to the imaging equipment or where the origin of the Frame Of Reference is located. It is important
that the position of the Patient and the origin are constant in relationship to a specific Frame Of
Reference.
 */
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.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
import cdac.medinfo.sdk.dcm30_04.exceptions.MandatoryMissingException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

// TODO: Auto-generated Javadoc
/*
 * Modified by PB on 8/8/07
 * The module holds its map of data in a collection wrapper called SingleCollection
 */
/**
 \* The class FrameOfReferenceModule.
 */
public class FrameOfReferenceModule extends Module   
{


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


	/**
	 * Instantiates a new frame of reference module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public FrameOfReferenceModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}
	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		//Data Element Hash Map
		objSingleCollection.add(new Tag(0x0020,0x0052));
		objSingleCollection.add(new Tag(0x0020,0x1040));
	}

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

		try
		{			//Check for the Type 1,2 Mandatory Attributes.
			if(!isPresent(0x0020,0x0052))
				throw new MandatoryMissingException(" 0020,0052");
			/*
			 * Condition : The Position Reference Indicator(0020,1040) shall be used only for annotation purposes and is not intended
			 * to be used as a mathematical spatial reference. This condition in not understandable.Need to review the
			 * validation for (0020,1040).
			 */
			if(!isPresent(0x0020,0x1040))
				throw new MandatoryMissingException(" 0020,1040");
		}
		catch(MandatoryMissingException mme)
		{

			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(mme.getMessage());

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

		}
		catch(ConditionFailedException fce)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(fce.getMessage());
			
				throw new InvalidModuleException(this.getClass().getSimpleName(), fce);
		}
		return true;
	}



	/**
	 * The method is used to set Uniquely identified frame of reference for a Series.
	 * The function accepts a String Value as the strStudyInstanceUID 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 strFrameOfReferenceUID - Unique identifier for the Study.
	 * 
	 * 
	 */
	public void setFrameOfReferenceUID(String strFrameOfReferenceUID)
	{
		/*Accept Uniquely identified frame of reference for a Series in String format of type UI.
		 * 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(0x0020, 0x0052, DicomConstants.DCM_DT_UI, strFrameOfReferenceUID);
	}

	/**
	 * The method is used to set Part of the patient's anatomy used as a reference.
	 * The function accepts a String Value as the strStudyInstanceUID 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 strPositionReferenceIndicator - String value for Position Reference Indicator
	 * 
	 * 
	 */
	public void setPositionReferenceIndicator(String strPositionReferenceIndicator)
	{
		/*Accept Part of the patient's anatomy used as a reference in String format of type LO.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0020, 0x1040, DicomConstants.DCM_DT_LO, strPositionReferenceIndicator);
	}
	
	/*Modified by AD on 29/06/07,
	 *following methods are actually getter functions that will be used to get the value
	 *for the specified tag. 
	 */
	/**
	 * Retrieves the Frame of reference UID.
	 * 
	 * @return - returns the frame of reference UID
	 */
	public String getFrameOfReferenceUID()
	{
		Object objectValue = getValue(0x0020, 0x0052);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Retrieves the Position Reference Indicator.
	 * 
	 * @return - returns the Position Reference Indicator
	 */
	public String getPositionReferenceIndicator()
	{
		Object objectValue = getValue(0x0020, 0x1040);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/*	 
	 * 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.
	 */
	/**
	 * This method returns the vector of keys representing the DataElements
	 * that belong to this module.
	 * 
	 * @return - the customized collection containing the dataelement tags
	 * that beling to this module
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}

}
