/*******************************************************************************
 *  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.services.mediacreation.dbhelper;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


import cdac.medinfo.sdk.dcm30_04.baselibs.DataSet;
import cdac.medinfo.sdk.dcm30_04.baselibs.DicomV3Factory;
import cdac.medinfo.sdk.dcm30_04.baselibs.ExplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.ImplicitDE;
import cdac.medinfo.sdk.dcm30_04.baselibs.SQ;
import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataTypeSQ;
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.ITag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITransferSyntax;
import cdac.medinfo.sdk.dcm30_04.enums.EnumExecutionStatus;
import cdac.medinfo.sdk.dcm30_04.services.dicomnetcommons.DataTypeConvertor;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.EnumFeatureList;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;

/**
 * MediaCreation_DBQuery interacts with database and performs queries fired.
 * It performs the queries fired for creation,updation and retrieval of Media Creation SOP Instances
 */
class MediaCreation_DBQuery 
{
	
	
	private Connection objcon = null;

	/**
	 * Sets connection
	 * @param objcon object of Connection
	 */
	public void setConnection(Connection objcon)
	{
		this.objcon = objcon;
	}

	/**
	 * Creates the SOPInstance.
	 * It inserts the information of all DataElements of provided Dataset  
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOPInstance UID
	 * @return boolean status as true or false
	 * @throws SQLException if SQL Operation fails
	 */
	boolean createMediaCreationInstance(IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException
	{
		String strTableName = "MEDIA_CREATION_DEINFO";
		
		String strValue = null;
		for(IDataElement objDataElement : objIDataSet)
		{
			/*
			 * This If-Else block inserts DataElements in database.
			 * It inserts all first level data elements and for SQ element it inserts that SQ element and all item elements belonging to that SQ.  
			 */
			IDicomValue objIDicomValue = objDataElement.getDicomValue();
			if(!(objIDicomValue instanceof SQ))
			{
				if(objIDicomValue.getValue() != null)
					strValue = DataTypeConvertor.dicomDatatoString(objIDicomValue);
				insertInstanceDEInfo(strTableName,strSOPInstanceUID,objIDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), false, null, strValue, null,null);
			}
			else
			{
				String strSQId = StandardMethods.generateUUID();
				insertInstanceDEInfo(strTableName,strSOPInstanceUID,objIDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), true, null, null, strSQId,null);
				insertSQInfo(strTableName,objIDicomValue,strSOPInstanceUID,strSQId,null);
			}
		}
		
		//populating table containing scheduling info for same sop instance
		createSchedulingInstance(getSchedulingDataset(objIDataSet), strSOPInstanceUID);
		return true;
	}
	
	//populates dataset with default information related to scheduling 
	private IDataSet getSchedulingDataset(IDataSet objIDataSet)
	{
		IDataSet objSchedulingDataset = new DataSet(objIDataSet.getTransferSyntax());
		ITransferSyntax objITransferSyntax = objSchedulingDataset.getTransferSyntax();
		IDictionaryReader objIDictionaryReader = objSchedulingDataset.getDictionaryReader();
		
		if(objIDataSet.isPresent(0x0008,0x0005))
			objSchedulingDataset.addDataElement(objIDataSet.getDataForTag(0x0008,0x0005));
		
		objSchedulingDataset.addDataElement(getDataElement(0x2100,0x0020, EnumExecutionStatus.IDLE.getValue(), objITransferSyntax, objIDictionaryReader));
		objSchedulingDataset.addDataElement(getDataElement(0x2100,0x0030, null, objITransferSyntax, objIDictionaryReader));
		objSchedulingDataset.addDataElement(getDataElement(0x2200,0x000B, (short)0, objITransferSyntax, objIDictionaryReader));
		objSchedulingDataset.addDataElement(getDataElement(0x0008,0x1198, null, objITransferSyntax, objIDictionaryReader));
		
		return objSchedulingDataset;
	}
	
	//Initializes a Dataelement
	private IDataElement getDataElement(int GroupNo,int ElementNo,Object objVal,ITransferSyntax objITransferSyntax,IDictionaryReader objDictionaryReader)
	{
		IDataElement objIDataElement = null;
		int iVRType = 0;
		if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			objIDataElement = new ImplicitDE(GroupNo,ElementNo,objVal,objITransferSyntax,objDictionaryReader);
		else
		{
			iVRType = StandardMethods.getiVRtype(objDictionaryReader.getVR(GroupNo, ElementNo));
			objIDataElement = new ExplicitDE(GroupNo,ElementNo,iVRType,objVal,objITransferSyntax,objDictionaryReader);
		}
		
		return objIDataElement;
	}

	/**
	 * Inserts scheduling information provided in dataset for given sop instance.
	 */
	void createSchedulingInstance(IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException
	{
		String strTableName = "MEDIA_SCHEDULE_DEINFO";

		String strValue = null;
		for(IDataElement objDataElement : objIDataSet)
		{
			/*
			 * This If-Else block inserts DataElements in database.
			 * It inserts all first level data elements and for SQ element it inserts that SQ element and all item elements belonging to that SQ.  
			 */
			IDicomValue objIDicomValue = objDataElement.getDicomValue();
			if(!(objIDicomValue instanceof SQ))
			{
				if(objIDicomValue.getValue() != null)
					strValue = DataTypeConvertor.dicomDatatoString(objIDicomValue);
				insertInstanceDEInfo(strTableName,strSOPInstanceUID,objIDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), false, null, strValue, null,null);
			}
			else
			{
				String strSQId = StandardMethods.generateUUID();
				insertInstanceDEInfo(strTableName,strSOPInstanceUID,objIDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), true, null, null, strSQId,null);
				insertSQInfo(strTableName,objIDicomValue,strSOPInstanceUID,strSQId,null);
			}
		}
	}
	
	/**
	 * Updates the SOPInstance information.
	 * It updates the information of all DataElements of provided Dataset  
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOPInstance UID
	 * @return boolean status as true or false
	 * @throws SQLException if SQL Operation fails
	 */
	public boolean updateScheduledInstanceInfo(IDataSet objIDataSet,String strSOPInstanceUID)throws SQLException
	{
		String strTableName = "MEDIA_SCHEDULE_DEINFO";
		ISingleCollection<MediaCreation_RowDescriptor> objRowCollection = populateRows(strTableName,strSOPInstanceUID);
		ICollectionIterator<IDataElement> objDEIterator = objIDataSet.iterator();
		String strValue = null;
		int iGroupNo,iElementNo;
		IDataElement objDataElement = null;
		IDicomValue objIDicomValue = null;
		while(objDEIterator.hasNext())
		{
			objDataElement = objDEIterator.next();
			objIDicomValue = objDataElement.getDicomValue();
			iGroupNo = objDataElement.getTag().getGroupNumber();
			iElementNo = objDataElement.getTag().getElementNumber();
			String strElementID = null;
			if(!(objIDicomValue instanceof SQ))
			{
				if(objIDicomValue.getValue() != null)
					strValue = DataTypeConvertor.dicomDatatoString(objIDicomValue);
				strElementID = getElementID(iGroupNo,iElementNo,objRowCollection);
				if(strElementID != null)
					updateRow(strValue,strElementID);
			}
			else
			{
				String strDelSQUID = getSQUID(iGroupNo,iElementNo,objRowCollection);
				deleteSequence(strDelSQUID);
				String strSQId = StandardMethods.generateUUID();
				insertInstanceDEInfo(strTableName,strSOPInstanceUID,objIDicomValue.getIVRType(), iGroupNo,iElementNo, true, null, null, strSQId,null);
				insertSQInfo(strTableName,objIDicomValue,strSOPInstanceUID,strSQId,null);
			}
		}
		return true;
	}
	
	/**
	 * Updates the value for a given unique DataElement ID
	 */
	private boolean updateRow(String strValue,String strDERowID)throws SQLException
	{
		String strQuery = "update MEDIA_SCHEDULE_DEINFO SET Value=?  where DERowID = '" + strDERowID + "'";
		PreparedStatement ps = objcon.prepareStatement(strQuery);
		ps.setString(1,strValue);
		ps.executeUpdate();

		return true;
	}
	
	/**
	 * Retrieves the SQUID for given Tag
	 */
	private String getSQUID(int iGroupNumber,int iElementNumber,ISingleCollection<MediaCreation_RowDescriptor> objRowCollection)
	{
		ICollectionIterator<MediaCreation_RowDescriptor> objRowIterator = objRowCollection.iterator();
		MediaCreation_RowDescriptor objNServiceRow = null;
		while(objRowIterator.hasNext())
		{
			objNServiceRow = objRowIterator.next();
			if(objNServiceRow.getGroupNumber() == iGroupNumber && objNServiceRow.getElementNumber() == iElementNumber && objNServiceRow.getParentSQUID() == null)
			{
				return objNServiceRow.getSQUID();
			}
		}
		return null;
	}
	
	/**
	 * Retrieves the unique DataElement Row ID for given Tag.
	 */
	private String getElementID(int iGroupNumber,int iElementNumber,ISingleCollection<MediaCreation_RowDescriptor> objRowCollection)
	{
		ICollectionIterator<MediaCreation_RowDescriptor> objRowIterator = objRowCollection.iterator();
		MediaCreation_RowDescriptor objMPPSRow = null;
		while(objRowIterator.hasNext())
		{
			objMPPSRow = objRowIterator.next();
			if(!objMPPSRow.isSQ() && objMPPSRow.getItemUID() == null && objMPPSRow.getGroupNumber() == iGroupNumber && objMPPSRow.getElementNumber() == iElementNumber)
			{
				objRowCollection.remove(objMPPSRow);
				return objMPPSRow.getDERowID();
			}
		}
		return null;
	}
	
	/**
	 * Retrieves the value of Execution status for given sop instance.
	 * @param strSOPInstanceUID value of SOP Instance UID 
	 * @return String value of step status.
	 * @throws SQLException if sql operation fails
	 */
	public String isSOPInstanceScheduled(String strSOPInstanceUID)throws SQLException
	{
		int group = 0x2100;
		int element = 0x0020;
		String query = "Select Value from MEDIA_SCHEDULE_DEINFO where SOPInstanceUID = '"+ strSOPInstanceUID + "' AND GroupNumber = "+group+" AND ElementNumber = "+element;
		PreparedStatement ps = objcon.prepareStatement(query);
		ResultSet rs = ps.executeQuery();
		String strValue = null;
		if(rs.next())
			strValue = rs.getString("Value");
		
		return strValue;
	}

	/**
	 * Checks whether provided SOP Instance is created or not.
	 * @param strSOPInstance value of SOP Instance UID 
	 * @return boolean shows status as success or failure
	 * @throws SQLException if sql operation fails
	 */
	boolean isSOPInstanceExist(String strSOPInstance)throws SQLException
	{
		String query = "Select Value from MEDIA_CREATION_DEINFO where SOPInstanceUID = '"+ strSOPInstance + "'";
		PreparedStatement ps = objcon.prepareStatement(query);
		ResultSet rs = ps.executeQuery();
		if(rs.next())
			return true;

		return false;
	}

	/**
	 * Retrieves the information of a given SOP Instance UID and populates the Dataset.
	 * @param objIDataSet instance of input Dataset
	 * @param strSOPInstanceUID value of SOPInstance UID
	 * @return objIDataSet instance of resultant Dataset
	 * @throws SQLException if SQL operation fails
	 */
	IDataSet retrieveMediaCreationInstanceInfo(ISingleCollection<ITag> objITagCollection,String strSOPInstanceUID)throws SQLException
	{
		String strTablename = "MEDIA_CREATION_DEINFO"; 
		IDataSet objResDataset = new DataSet();
		ISingleCollection<MediaCreation_RowDescriptor> objRowCollection = populateRows(strTablename,strSOPInstanceUID);
		if(objRowCollection.size() == 0)
			return null;
		generateDataSet(objResDataset,objRowCollection,objITagCollection);
		return objResDataset;
	}
	
	/**
	 * Retrieves the information of a given SOP Instance UID and populates the Dataset.
	 * @param objIDataSet instance of input Dataset
	 * @param strSOPInstanceUID value of SOPInstance UID
	 * @return objIDataSet instance of resultant Dataset
	 * @throws SQLException if SQL operation fails
	 */
	IDataSet retrieveScheduledInstanceInfo(ISingleCollection<ITag> objITagCollection,String strSOPInstanceUID)throws SQLException
	{
		String strTablename = "MEDIA_SCHEDULE_DEINFO"; 
		IDataSet objResDataset = new DataSet();
		ISingleCollection<MediaCreation_RowDescriptor> objRowCollection = populateRows(strTablename,strSOPInstanceUID);
		if(objRowCollection.size() == 0)
			return null;
		generateDataSet(objResDataset,objRowCollection,objITagCollection);
		return objResDataset;
	}

	/**
	 * Inserts DataElement of a sequence and all its Items.
	 */
	private boolean insertSQInfo(String strTableName,IDicomValue objIDicomValue,String strSOPInstanceUID,String strSQUUid,String strParentSQID)throws SQLException
	{
		SQ objSQDicomValue = (SQ)objIDicomValue;
		ICollectionIterator<IItem> objSQItemIterator = objSQDicomValue.iterator();
		String strValue = null;
		while(objSQItemIterator.hasNext())
		{
			/*
			 * Iterating over Items of provided sequence and inserting DataElements which are not SQ.
			 * for SQ it recursively calls itself with changed SQUUID and ParentSQID.
			 * A sequence and all 
			 */
			IItem objItem = objSQItemIterator.next();
			String strItemUUID = StandardMethods.generateUUID();
			ICollectionIterator<IDataElement> objDEIterator = objItem.iterator();
			while(objDEIterator.hasNext())
			{
				IDataElement objDataElement = objDEIterator.next();
				IDicomValue objTempDicomValue = objDataElement.getDicomValue();
				if(!(objTempDicomValue instanceof SQ))
				{
					if(objTempDicomValue.getValue() != null)
						strValue = DataTypeConvertor.dicomDatatoString(objTempDicomValue);
					insertInstanceDEInfo(strTableName,strSOPInstanceUID,objTempDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), false, strParentSQID, strValue, strSQUUid,strItemUUID);
				}
				else
				{
					String strSQId = StandardMethods.generateUUID();
					insertInstanceDEInfo(strTableName,strSOPInstanceUID,objTempDicomValue.getIVRType(), objDataElement.getTag().getGroupNumber(),objDataElement.getTag().getElementNumber(), true, strSQUUid, null, strSQId,strItemUUID);
					insertSQInfo(strTableName,objTempDicomValue, strSOPInstanceUID,strSQId,strSQUUid);
				}
			}
		}
		return true;
	}

	/**
	 * Delete information of a Sequence form Database for given SQ UID.
	 */
	private void deleteSequence(String strSQUID)throws SQLException
	{
		String query = "Select * from MEDIA_SCHEDULE_DEINFO where SQUUID = '"+ strSQUID + "'";
		PreparedStatement ps = objcon.prepareStatement(query);
		ResultSet rs = ps.executeQuery();
		String isSQ = null;
		//String strItemID = null;
		while(rs.next())
		{
			isSQ = rs.getString("IsSQ");
			if(isSQ.equalsIgnoreCase("Y"))
			{
				String strQry = "delete from MEDIA_SCHEDULE_DEINFO where DERowID = '" + rs.getString("DERowID") + "'";
				PreparedStatement objPreparedStatement = objcon.prepareStatement(strQry);
				objPreparedStatement.executeUpdate();
			}
			else
			{
				deleteItemRows(rs.getString("ItemUUID"));
			}
		}
		String strQuery = "delete from MEDIA_SCHEDULE_DEINFO where SQUUID = '" + strSQUID +"'";

		ps = objcon.prepareStatement(strQuery);
		ps.executeUpdate();
	}

	/**
	 * Delete information of a Item form Database for given Item UID.
	 */
	private void deleteItemRows(String strItemUID)throws SQLException
	{
		String query = "Select * from MEDIA_SCHEDULE_DEINFO where ItemUUID = '"+ strItemUID + "'";
		PreparedStatement ps = objcon.prepareStatement(query);
		ResultSet rs = ps.executeQuery();
		String isSQ = null;
		while(rs.next())
		{
			isSQ = rs.getString("IsSQ");
			if(isSQ.equalsIgnoreCase("Y"))
				deleteSequence(rs.getString("SQUUID"));
			else
			{
				String strQry = "delete from MEDIA_SCHEDULE_DEINFO where DERowID = '" + rs.getString("DERowID") + "'";
				PreparedStatement objPreparedStatement = objcon.prepareStatement(strQry);
				objPreparedStatement.executeUpdate();
			}
		}
	}

	/**
	 * Inserts the information of DataElement in Database
	 */
	private boolean insertInstanceDEInfo(String strTableName,String strSOPInstanceUID,int iVRType,int iGroupNumber,int iElementNumber,boolean isSQ,String strParentSQID,String strValue,String strSQID,String strItemID)throws SQLException
	{
		String strQuery = "insert into " +strTableName+" (DERowID,SOPInstanceUID,VRType,GroupNumber,ElementNumber,IsSQ,ParentSQUID,Value,SQUUID,ItemUUID) values (?,?,?,?,?,?,?,?,?,?)";

		PreparedStatement ps = objcon.prepareStatement(strQuery);
		ps.setString(1,StandardMethods.generateUUID());
		ps.setString(2,strSOPInstanceUID);
		ps.setInt(3,iVRType);
		ps.setInt(4,iGroupNumber);
		ps.setInt(5,iElementNumber);
		if(isSQ)
			ps.setString(6,"Y");
		else
			ps.setString(6,"N");
		ps.setString(7,strParentSQID);
		ps.setString(8,strValue);
		ps.setString(9,strSQID);
		ps.setString(10,strItemID);
		ps.executeUpdate();

		return true;
	}

	/**
	 * Populates the collection of RowDescriptor for a given SOP Instance UID
	 */
	private ISingleCollection<MediaCreation_RowDescriptor> populateRows(String strTableName,String strSOPInstanceUID)throws SQLException
	{
		ISingleCollection<MediaCreation_RowDescriptor> objRowCollection = new SingleCollection<MediaCreation_RowDescriptor>();
		String query = "Select * from " + strTableName + " where SOPInstanceUID = '"+ strSOPInstanceUID + "'";
		PreparedStatement ps = objcon.prepareStatement(query);
		ResultSet rs = ps.executeQuery();
		MediaCreation_RowDescriptor objRowDescriptor = null;
		while(rs.next())
		{
			objRowDescriptor = new MediaCreation_RowDescriptor();
			objRowDescriptor.setDERowID(rs.getString("DERowID"));
			objRowDescriptor.setVRType(rs.getInt("VRType"));
			objRowDescriptor.setGroupNumber(rs.getInt("GroupNumber"));
			objRowDescriptor.setElementNumber(rs.getInt("ElementNumber"));
			String isSQ = rs.getString("IsSQ");
			if(isSQ.equalsIgnoreCase("Y"))
				objRowDescriptor.setSQ(true);
			else
				objRowDescriptor.setSQ(false);
			objRowDescriptor.setParentSQUID(rs.getString("ParentSQUID"));
			objRowDescriptor.setValue(rs.getString("Value"));
			objRowDescriptor.setSQUID(rs.getString("SQUUID"));
			objRowDescriptor.setItemUID(rs.getString("ItemUUID"));
			objRowCollection.add(objRowDescriptor);
		}
		return objRowCollection;
	}

	/**
	 * Populates the Dataset from given collection of Dataelements Rows according to the queried Dataset.
	 */
	private void generateDataSet(IDataSet objIDataSet,ISingleCollection<MediaCreation_RowDescriptor> objRowsCollection,ISingleCollection<ITag> objITagCollection)
	{
		IDictionaryReader objIDictionaryReader = objIDataSet.getDictionaryReader();
		ITransferSyntax objITransferSyntax = objIDataSet.getTransferSyntax();
		IDataElement objIDataElement = null;
		int iGroupNumber,iElementNumber;

		populateFirstLevelDE(objIDataSet, objRowsCollection,objITagCollection);

		ICollectionIterator<MediaCreation_RowDescriptor> objRowsIterator = objRowsCollection.iterator();
		while(objRowsIterator.hasNext())
		{
			MediaCreation_RowDescriptor objRow = objRowsIterator.next();
			iGroupNumber = objRow.getGroupNumber();
			iElementNumber = objRow.getElementNumber();
			if(objRow.isSQ() && objRow.getParentSQUID() == null)
			{
				IDataTypeSQ objSQ = DicomV3Factory.createInstance().createSequence(iGroupNumber, iElementNumber, objIDataSet.getTransferSyntax());

				objRowsCollection.remove(objRow);
				//Populates the all Items of this sequence 
				createSequence(objSQ,objRow.getSQUID(),objRowsCollection);
				//Adding the SQ Item in Dataset
				objRowsIterator = objRowsCollection.iterator();
				if(objITagCollection == null || objITagCollection.contains(new Tag(iGroupNumber, iElementNumber)))
				{
					//Adding the SQ Item in Dataset
					if(objITransferSyntax.getVRTransferSyntax()==DicomConstants.DCM_VR_IMPLICIT)
						objIDataElement = new ImplicitDE(iGroupNumber, iElementNumber,objSQ,objSQ.getTransferSyntax(),objIDictionaryReader);
					else
						objIDataElement = new ExplicitDE(iGroupNumber,iElementNumber,DicomConstants.DCM_DT_SQ,objSQ);
					objIDataSet.addDataElement(objIDataElement);
				}
			}
		}
	}

	/**
	 * Populates the first level Dataelements in Dataset
	 */
	private void populateFirstLevelDE(IDataSet objRstDataSet,ISingleCollection<MediaCreation_RowDescriptor> objobjMPPS_RowsList,ISingleCollection<ITag> objITagCollection)
	{
		IDictionaryReader objIDictionaryReader = objRstDataSet.getDictionaryReader();
		ITransferSyntax objITransferSyntax = objRstDataSet.getTransferSyntax();
		IDataElement objIDataElement = null;
		int iVRType,iGroupNumber,iElementNumber;
		ICollectionIterator<MediaCreation_RowDescriptor> objIterator = objobjMPPS_RowsList.iterator();
		while(objIterator.hasNext())
		{
			MediaCreation_RowDescriptor objRow = objIterator.next();
			iGroupNumber = objRow.getGroupNumber();
			iElementNumber = objRow.getElementNumber();
			iVRType = objRow.getVRType();
			if(!objRow.isSQ() && objRow.getItemUID() == null)
			{
				if(objITagCollection == null || objITagCollection.contains(new Tag(iGroupNumber, iElementNumber)))
				{
					objIDataElement = DataTypeConvertor.stringtoDataElement(objRow.getValue(),iGroupNumber,iElementNumber,iVRType,objITransferSyntax,objIDictionaryReader);

					objRstDataSet.addDataElement(objIDataElement);
				}
				objobjMPPS_RowsList.remove(objRow);
				objIterator = objobjMPPS_RowsList.iterator();
			}
		}
	}

	/**
	 * Populates the Dataset with a Sequence and all its Items information 
	 */
	private void createSequence(IDataTypeSQ objSQ,String strSQUID,ISingleCollection<MediaCreation_RowDescriptor> objMPPS_RowsList)
	{
		ICollectionIterator<MediaCreation_RowDescriptor> objRowsIterator = objMPPS_RowsList.iterator();
		while(objRowsIterator.hasNext())
		{
			MediaCreation_RowDescriptor objRow = objRowsIterator.next();
			if(!objRow.isSQ() && objRow.getSQUID() != null && objRow.getSQUID().equals(strSQUID))
			{
				IItem objItem = objSQ.getNewItem();
				createSQItems(objItem, objRow.getItemUID(),objMPPS_RowsList);
				objRowsIterator = objMPPS_RowsList.iterator();
				objSQ.addItem(objItem);
			}
		}
	}

	/**
	 * Populates the Item with information of all its DataElements 
	 */
	private void createSQItems(IItem objItem , String strItemUid,ISingleCollection<MediaCreation_RowDescriptor> objMPPS_RowsList)
	{
		int iVRType,iGroupNumber,iElementNumber;
		IDictionaryReader objIDictionaryReader = objItem.getDictionaryReader();
		ITransferSyntax objITransferSyntax = objItem.getTransferSyntax();
		IDataElement objIDataElement = null;
		ICollectionIterator<MediaCreation_RowDescriptor> objRowsIterator = objMPPS_RowsList.iterator();
		while(objRowsIterator.hasNext())
		{
			MediaCreation_RowDescriptor objRow = objRowsIterator.next();
			iGroupNumber = objRow.getGroupNumber();
			iElementNumber = objRow.getElementNumber();
			iVRType = objRow.getVRType();
			if(objRow.getItemUID() != null && objRow.getItemUID().equals(strItemUid))
			{
				if(!objRow.isSQ())
				{
					objIDataElement = DataTypeConvertor.stringtoDataElement(objRow.getValue(),iGroupNumber,iElementNumber,iVRType,objITransferSyntax,objIDictionaryReader);
					objItem.addDataElement(objIDataElement);

					objMPPS_RowsList.remove(objRow);
					objRowsIterator = objMPPS_RowsList.iterator();
				}
				else if(objRow.isSQ())
				{
					IDataTypeSQ objSQ = DicomV3Factory.createInstance().createSequence(iGroupNumber, iElementNumber, objItem.getTransferSyntax());
					objMPPS_RowsList.remove(objRow);
					//Populates the all Items of this sequence 
					createSequence(objSQ,objRow.getSQUID(),objMPPS_RowsList);
					objRowsIterator = objMPPS_RowsList.iterator();
					//Adding the SQ DicomValue in Item
					if(objITransferSyntax.getVRTransferSyntax()==DicomConstants.DCM_VR_IMPLICIT)
						objIDataElement = new ImplicitDE(iGroupNumber, iElementNumber,objSQ,objSQ.getTransferSyntax(),objIDictionaryReader);
					else
						objIDataElement = new ExplicitDE(iGroupNumber,iElementNumber,DicomConstants.DCM_DT_SQ,objSQ);
					objItem.addDataElement(objIDataElement);
				}
			}
		}
	}
}
