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

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDictionaryDataProvider;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;

/**
 * DictionaryDataProvider is a class which implements Interface IDictionaryDataProvider. The interface specifies
 * the required functionality for the data dictionary to be populated according to the DICOM PS3 2004 standard.
 * 
 * The data dictionary contains description of data elements which consists of name, value representation, min and max 
 * value multiplicity and status indicating whether the element is retired in this version or not.
 * 
 * IDictionaryDataProvider interface represents the runtime representation of the dictionary. User can create any runtime
 * data holder classes for each entry as defined in DICOM standard. The user needs to provide data to makeEntry method of
 * DictionaryDataProvider which basically passes the data to these runtime classes. Once the dictionary is populated through populate method,
 * DictionaryDataProvider can be used to access the data. 
 * Any implementation of IDictionaryDataProvider should provide mechanism to retrieve the data 
 * 
 * How SDK's default implementation works?
 * 
 * 		DictionaryDataProvider internally holds the data provided to it through makeEntry method. If user implements IDicitonaryDataProvider
 * 		interface, then he/she has to internally maintain the data provided by makeEntry method. There is no need to extend
 *  	from DictionaryDataProvider if user don't want to internally maintain the data provided by makeEntry method.
 *       
 * 		DictionaryReader reads dictionary data from xml file through populate method. If user implements IDictionaryReader interface,
 * 		he/she has to give the implementation of populate method. If user extends from DictionaryReader class, then he/she has to override the
 * 		populate method in which he/she has to call makeEntry method of DictionaryDataProvider.
 * 
 */

public class DictionaryDataProvider implements IDictionaryDataProvider  
{
	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1L;
	
	DataDictionary objDataDictionary = null;
	final int maskInt = 0xFFFFFF00;

	/**
	 * Default Constructor for DictionaryDataProvider which creates an instance of DataDictionary.
	 */
	public DictionaryDataProvider()
	{
		objDataDictionary = DataDictionary.createInstance();
	}

	/**
	 * This method makes an entry in DataDictionary for given values of fields for an element.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @param strElementName Name of the attribute.
	 * @param strVR string value of VR type of an element.
	 * @param iMinVM Minimum integer value multiplicity of an element.
	 * @param iMaxVM Maximum integer value multiplicity of an element.
	 * @param isRetired - Shows the current status of element.
	 */
	public void makeEntry(int iGroupNumber, int iElementNumber, String strElementName, String strVR, int iMinVM, int iMaxVM, boolean isRetired)
	{
		RowDescriptor objRowDescriptor = new RowDescriptor(iGroupNumber,iElementNumber,strElementName,strVR,iMinVM,iMaxVM,isRetired);
		objDataDictionary.add(objRowDescriptor);
	}

	/**
	 * Retrieves the name of the element.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return String - name of the element.
	 */
	public String getName(int iGroupNumber, int iElementNumber)
	{
		RowDescriptor objRowDescriptor = objDataDictionary.getEntry(iGroupNumber, iElementNumber);
		if(objRowDescriptor != null)
			return objRowDescriptor.getStrElementName();
		return null;
	}

	/**
	 * Retrieves the VR type of the element. VR Type represents the Value Representation 
	 * for the specified Tag.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return String - VR type of the element.
	 */
	public String getVR(int iGroupNumber, int iElementNumber)
	{
		if((iGroupNumber >= 0x5000 && iGroupNumber<= 0x50FF) || (iGroupNumber >= 0x6000 && iGroupNumber<= 0x60FF))
			iGroupNumber = iGroupNumber & maskInt;

		RowDescriptor objRowDescriptor = objDataDictionary.getEntry(iGroupNumber, iElementNumber);
		if(objRowDescriptor != null)
			return objRowDescriptor.getStrVR();
		return null;
	}

	/**
	 * Retrieves the minimum value multiplicity of the element.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return int - integer value of minimum value multiplicity
	 */
	public int getMinVM(int iGroupNumber, int iElementNumber)
	{
		RowDescriptor objRowDescriptor = objDataDictionary.getEntry(iGroupNumber, iElementNumber);
		if(objRowDescriptor != null)
			return objRowDescriptor.getMinVM();
		return DicomConstants.DCM_FUNCTION_STATUS_FAIL;
	}

	/**
	 * Retrieves the maximum value multiplicity of the element.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return int - integer value of maximum value multiplicity
	 */
	public int getMaxVM(int iGroupNumber, int iElementNumber)
	{
		RowDescriptor objRowDescriptor = objDataDictionary.getEntry(iGroupNumber, iElementNumber);
		if(objRowDescriptor != null)
			return objRowDescriptor.getMaxVM();
		return DicomConstants.DCM_FUNCTION_STATUS_FAIL;
	}

	/**
	 * Checks the current status of element whether it's retired or not.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return boolean - shows status of element.
	 */
	public boolean isRetired(int iGroupNumber, int iElementNumber)
	{
		RowDescriptor objRowDescriptor = objDataDictionary.getEntry(iGroupNumber, iElementNumber);
		if(objRowDescriptor != null)
			return objRowDescriptor.isBoolRET();
		return false;
	}

	/**
	 * This method checks that given group number is present or not.
	 * @param iGroupNumber Integer value of group number.
	 * @return boolean - shows presence of group number.
	 */
	public boolean isGroupNumberPresent(int iGroupNumber)
	{
		return true;
	}

	/**
	 * This method checks that given element number is present or not.
	 * @param iElementNumber Integer value of element number.
	 * @return boolean - shows presence of element number.
	 */
	public boolean isElementNumberPresent(int iElementNumber)
	{
		return true;
	}

	/**
	 * This method checks that given VR type is present or not.
	 * VR Type represents the Value Representation for the specified Tag
	 * @param strVR string value of VR type.
	 * @return boolean - shows presence of VR type.
	 */
	public boolean isVRPresent(String strVR)
	{
		return true;
	}

	/**
	 * This method checks that given group number and element number contructs a valid tag.
	 * @param iGroupNumber Integer value of group number.
	 * @param iElementNumber Integer value of element number.
	 * @return boolean - shows validity of tag.
	 */
	public boolean isStandardTag(int iGroupNumber, int iElementNumber)
	{
		return true;
	}

	/**
	 * Checks that data dictionary is populated or not.
	 * @return boolean - shows status of dictionary.
	 */
	public boolean isPopulated()
	{
		return objDataDictionary.isPopulated();
	}
	
	/**
	 * Retrieves the  Group Number and Element Number of Attribute Name provided.
	 * This function return a short array in which element at index 0 is Group Number
	 * and at index 1 is Element Number. 
	 * @param strDataElementName String value of Data Element name.
	 * @return short[] - return short array. The element at index 0 represents Group Number and 
	 * at index 1 represents Element Number. 
	 */
	public short[] getTag(String strDataElementName)
	{
		return objDataDictionary.getTag(strDataElementName);
	}
}

