/*******************************************************************************
 *  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.tools.dcm2xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import cdac.medinfo.sdk.dcm30_04.baselibs.OB;
import cdac.medinfo.sdk.dcm30_04.baselibs.OBImageObject;
import cdac.medinfo.sdk.dcm30_04.baselibs.OW;
import cdac.medinfo.sdk.dcm30_04.baselibs.OWImageObject;
import cdac.medinfo.sdk.dcm30_04.baselibs.SQ;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
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.dicomparserserializers.DicomParser;
import cdac.medinfo.sdk.dcm30_04.enums.EnumLoggingLevel;

import cdac.medinfo.sdk.dcm30_04.services.dicomnetcommons.DataTypeConvertor;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.StandardMethods;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;


/**
 * Utility class for conversion of DICOM file to XML Document.
 */
public class DCM2XMLConverter 
{
	private Text txtContentNode = null;
	static int lengthOfOption = 18;
	static int lengthOfDetails = 79 - lengthOfOption;

	public static void main(String[] args) 
	{
		EnumLoggingLevel enumlogginglevel = EnumLoggingLevel.SEVERE;
		String strLogDir = null;
		
		DCM2XMLConverter objDCM2XMLConverter = new DCM2XMLConverter();
		String strDCMFile = null;
		String strDestFolder = null;

		String strIniFile = null;
		String strKey = null;


		if(args == null || args.length == 0)
		{
			objDCM2XMLConverter.displayHelp();
			System.exit(0);
		}

		for(int i = 0; i < args.length; i++)
		{
			if(args[i].equalsIgnoreCase("-l") && args.length > i + 1)
			{
				String strLoggingMode= args[i + 1];
				if(strLoggingMode.equalsIgnoreCase("i"))
				{
					enumlogginglevel = EnumLoggingLevel.INFO;
				} else
					if(strLoggingMode.equalsIgnoreCase("s"))
					{
						enumlogginglevel = EnumLoggingLevel.SEVERE;
					} else
					{
						System.out.println("Not a Valid Command. The value of logging mode can be INFO(I) or SEVER(S)");
						objDCM2XMLConverter.displayHelp();
						System.exit(0);
					}
				i++;
				continue;
			}
			if(args[i].equalsIgnoreCase("-d") && args.length > i + 1)
			{
				strLogDir = args[i + 1];
				i++;
				continue;
			}
			if(args[i].equalsIgnoreCase("-v") && args.length > i + 1)
			{

				i++;
				continue;
			}
			if(args[i].equalsIgnoreCase("-f") && args.length > i + 1)
			{
				strDCMFile = args[i + 1];
				i++;
				continue;
			}	
			if(args[i].equalsIgnoreCase("-s") && args.length > i + 1)
			{
				strDestFolder = args[i + 1];
				i++;
				continue;
			}
			if (args[i].trim().equalsIgnoreCase("-z") && args.length > i + 1)
			{
				String temp = args[i + 1].trim();
				String[] valueArray = temp.split("#");
				if (valueArray.length != 2)
				{
					System.out.println("Not a valid command");
					objDCM2XMLConverter.displayHelp();
					System.exit(0);
				}
				strIniFile = valueArray[0];
				strKey = valueArray[1];
				i++;
				continue;
			}
		}

		try
		{
			DicomConfig dicomconfig = DicomConfig.createInstance();
			dicomconfig.enableLogging(enumlogginglevel, strLogDir);
		
			if(strDCMFile != null)
			{

				DicomParser objDicomParser = new DicomParser();
				IDataSet objSRCDataSet = objDicomParser.parseAsPart10File(strDCMFile,true);		

				if(strDestFolder != null)				
					objDCM2XMLConverter.serializeXMLDoc(objSRCDataSet, strDestFolder);
				else
					objDCM2XMLConverter.serializeXMLDoc(objSRCDataSet, System.getProperty("java.io.tmpdir")+"/CDAC-SDK/DCM-J/DicomDump/");
			}
			else
			{			
				System.out.println("Not a valid command, Source DICOM file for XML conversion is not specified.");
				objDCM2XMLConverter.displayHelp();
				System.exit(0);
			}
		}
		catch(Exception exception)
		{
			System.out.println("Operation failed :" + exception.getMessage());
		}
	}



	private void displayHelp()
	{
		System.out.println("\nDCM2XML :: Converts the DICOM file to XML document.");

		System.out.println("\nDCM2XML [-d LogDir]  [-l LogMode] " +
		"-f DCMfile \n [-s DestinationFolder] \n");

		printToConsole("-d", "Log directory");
		printToConsole("", "User's temp directory is taken as default.");

		printToConsole("-l", "Log mode");
		String as1[] = {
				"I INFO", "S SEVER"
		};
		printToConsole("LogMode", as1);
		printToConsole("", "Default Logging Mode is INFO");
		printToConsole("-f", "Source DICOM file for XML conversion.");
		printToConsole("-s", "Destination folder path to store converted xml file.");
		printToConsole("", "User's temp directory is taken as default.");

		System.out.println("\nExample :");

		System.out.println("\n1. DCM2XML -f image.dcm -s C:/XMLContent " +
		"\nConverts the image.dcm to its XML representation and stores same to folder \nC:/XMLContent.");

	}

	/**
	 * Display Help of command on console in proper manner.
	 * @param strOption Option for command.
	 * @param strDetails Description of option.
	 */
	public static void printToConsole(String strOption, String strDetails)
	{
		String strBuffer = "";
		if (strOption != null)
			strBuffer = strBuffer + strOption ;
		while (lengthOfOption > strBuffer.length())
		{
			strBuffer = strBuffer + " ";
		}
		if (strDetails != null)
		{
			if (strDetails.length() < lengthOfDetails || strDetails.length() == lengthOfDetails)
			{
				strBuffer = strBuffer + strDetails;
				strDetails = null;
			}
			else
			{
				strBuffer = strBuffer + strDetails.substring(0, lengthOfDetails);
				strDetails = strDetails.substring(lengthOfDetails, (strDetails.length() ));
			}
		}

		System.out.println(strBuffer);
		if (strDetails == null)
			return;
		else
			printToConsole(null, strDetails);
	}

	/**
	 * Display Help of command on console in proper manner.
	 * @param strAttribute Attribute for option.
	 * @param strDesc Description of attributes.
	 */
	public static void printToConsole(String strAttribute, String[] strDesc)
	{
		if (strDesc.length > 1)
			printToConsole(strAttribute, strDesc[0]);
		for(int i = 1;i<strDesc.length;i++)
			printToConsole(null, strDesc[i]);
	}


	/**
	 * Creates the SR document in the form of XML file.
	 * @param objIDataSet Object of IDataSet.
	 * @param path  Complete path with name where SR document will be kept.
	 * @return boolean value i. e. true or false.
	 */
	public boolean serializeXMLDoc(IDataSet objIDataSet,String strPath) throws Exception
	{

		File objFile = null;	
		String strStudyInstanceUID = objIDataSet.getValue(0x0020,0x000D).toString();

		objFile = new File(strPath );
		objFile.mkdirs();

		String strDocumentName = null;

		if(!strPath.endsWith("/"))
			strDocumentName = strPath + "/" + strStudyInstanceUID+".xml";
		else
			strDocumentName = strPath + strStudyInstanceUID+".xml";


		objFile = new File(strDocumentName);

		//Creating Document object
		Document dom = null;

		//get an instance of factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

		//get an instance of builder
		DocumentBuilder db = dbf.newDocumentBuilder();

		//create an instance of DOM
		dom = db.newDocument();

		// Root Element
		Element rootEle = null;

		// Starts the process of XML Serialization which can throw IOException		
		serializeDataSet(dom, rootEle, objIDataSet);

		//print
		OutputFormat format = new OutputFormat(dom);

		format.setIndenting(true);		      
		format.setEncoding("ISO-8859-1");
		format.setVersion("1.0");		   
		format.setLineSeparator(System.getProperty("line.separator"));

		//to generate output to console use this serializer
		XMLSerializer serializer = new XMLSerializer(System.out, format);

		//to generate a file output use fileoutputstream instead of system.out
		serializer = new XMLSerializer(new FileOutputStream(new File(strDocumentName)), format);

		serializer.serialize(dom);

		System.out.println("\nXML Representation of specified DICOM file stored at " + strDocumentName);

		return true;
	}


	private void serializeDataSet(Document dom, Element eleDocument, IDataSet objIDataSet) throws IOException
	{
		ICollectionIterator<IDataElement> objIDataSetIterator = objIDataSet.iterator();
		eleDocument =	dom.createElement("DICOMFILE");
		dom.appendChild(eleDocument);

		Element eleDicomHeader = dom.createElement("Header");
		Element eleTransferSyntaxUID = dom.createElement("TransferSyntaxUID");
		txtContentNode = dom.createTextNode(objIDataSet.getTransferSyntax().getTransferSyntaxUID());
		eleTransferSyntaxUID.appendChild(txtContentNode);
		eleDicomHeader.appendChild(eleTransferSyntaxUID);
		eleDocument.appendChild(eleDicomHeader);

		Element eleDicomDataSet =	dom.createElement("DicomDataSet");
		eleDocument.appendChild(eleDicomDataSet);


		Element tmpDEElement = null; 
		int iGroupNumber,iElementNumber;
		String strDEDescription = null;
		IDataElement objDataElement = null;
		IDicomValue objIDicomValue = null;

		while(objIDataSetIterator.hasNext())
		{
			objDataElement = objIDataSetIterator.next();				
			iGroupNumber = objDataElement.getTag().getGroupNumber();
			iElementNumber = objDataElement.getTag().getElementNumber();
			objIDicomValue = objDataElement.getDicomValue();

			if(objIDicomValue instanceof OBImageObject ||objIDicomValue instanceof OWImageObject
					|| objIDicomValue instanceof OB || objIDicomValue instanceof OW)
			{
				serializeImageElement(dom,eleDicomDataSet,objDataElement,objIDataSet.getDictionaryReader());
			}			
			else if(!(objIDicomValue instanceof SQ))
			{
				if(null != objIDicomValue.toString())
				{
					strDEDescription = objIDataSet.getDictionaryReader().getName(iGroupNumber,iElementNumber);

					if(null != strDEDescription)
					{					
						strDEDescription = strDEDescription.replaceAll("\\p{Space}","");
						strDEDescription = strDEDescription.replaceAll("\\p{Punct}","");
						tmpDEElement = dom.createElement(strDEDescription);	
						txtContentNode = dom.createTextNode(DataTypeConvertor.dicomDatatoString(objIDicomValue));
						tmpDEElement.appendChild(txtContentNode);
						tmpDEElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(iGroupNumber));
						tmpDEElement.setAttribute("ElementNumber","0x"+Integer.toHexString(iElementNumber));
						tmpDEElement.setAttribute("Length", Integer.toString(objIDicomValue.getValueLength()));
						tmpDEElement.setAttribute("VRType",StandardMethods.getStrVRtype(objIDicomValue.getIVRType()));
					}
					else
					{
						strDEDescription = "Private";
						tmpDEElement = dom.createElement(strDEDescription);	
						txtContentNode = dom.createTextNode(DataTypeConvertor.dicomDatatoString(objIDicomValue));
						tmpDEElement.appendChild(txtContentNode);
						tmpDEElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(iGroupNumber));
						tmpDEElement.setAttribute("ElementNumber","0x"+Integer.toHexString(iElementNumber));
						tmpDEElement.setAttribute("VRType",StandardMethods.getStrVRtype(objIDicomValue.getIVRType()));
						tmpDEElement.setAttribute("Length", Integer.toString(objIDicomValue.getValueLength()));
					}
					eleDicomDataSet.appendChild(tmpDEElement);
					tmpDEElement = null;
				}
			}
			else  
			{	
				// Serialize Sequence
				serialzeSequence(dom,eleDicomDataSet,objDataElement);
			}	
		}
	}



	private void serialzeSequence(Document dom,Element eleHeader, IDataElement objSQIDataElement) throws IOException 
	{
		SQ objSQValue = (SQ)objSQIDataElement.getDicomValue();
		ICollectionIterator<IItem> objSQItemIterator =objSQValue.iterator();

		//Add Sequence Node
		Element tempSQElement  = dom.createElement(objSQValue.getClass().getSimpleName());
		tempSQElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(objSQIDataElement.getTag().getGroupNumber()));
		tempSQElement.setAttribute("ElementNumber","0x"+Integer.toHexString(objSQIDataElement.getTag().getElementNumber()));
		tempSQElement.setAttribute("VRType",StandardMethods.getStrVRtype(objSQValue.getIVRType()));
		tempSQElement.setAttribute("Length", Integer.toString(objSQIDataElement.getValueLength()));

		Element tempITEMElement = null ;
		Element tmpDEElement = null;
		String strDEDescription = null;
		int iGroupNumber,iElementNumber;
		IDataElement objDataElement = null;
		IDicomValue objIDicomValue = null;


		while(objSQItemIterator.hasNext())
		{
			IItem objItem = objSQItemIterator.next();
			ICollectionIterator<IDataElement> objDataElementIterator = objItem.iterator();			
			tempITEMElement = dom.createElement(objItem.getClass().getSimpleName());

			while(objDataElementIterator.hasNext())
			{
				objDataElement = objDataElementIterator.next();
				iGroupNumber = objDataElement.getTag().getGroupNumber();
				iElementNumber = objDataElement.getTag().getElementNumber();
				objIDicomValue = objDataElement.getDicomValue();

				if(objIDicomValue instanceof OBImageObject ||objIDicomValue instanceof OWImageObject
						|| objIDicomValue instanceof OB || objIDicomValue instanceof OW)
				{
					serializeImageElement(dom,tempITEMElement,objDataElement,objSQValue.getDictionaryReader());
				}
				else if(!(objIDicomValue instanceof SQ))
				{
					if(null != objIDicomValue.toString())
					{
						strDEDescription = objSQValue.getDictionaryReader().getName(iGroupNumber, iElementNumber);						

						if(null != strDEDescription)
						{
							strDEDescription = strDEDescription.replaceAll("\\p{Space}","");
							strDEDescription = strDEDescription.replaceAll("\\p{Punct}","");
							tmpDEElement = dom.createElement(strDEDescription);	
							txtContentNode = dom.createTextNode(DataTypeConvertor.dicomDatatoString(objIDicomValue));
							tmpDEElement.appendChild(txtContentNode);
							tmpDEElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(iGroupNumber));
							tmpDEElement.setAttribute("ElementNumber","0x"+Integer.toHexString(iElementNumber));
							tmpDEElement.setAttribute("Length", Integer.toString(objIDicomValue.getValueLength()));
							tmpDEElement.setAttribute("VRType",StandardMethods.getStrVRtype(objIDicomValue.getIVRType()));

						}
						else
						{
							strDEDescription = "Private";
							tmpDEElement = dom.createElement(strDEDescription);	
							txtContentNode = dom.createTextNode(DataTypeConvertor.dicomDatatoString(objIDicomValue));
							tmpDEElement.appendChild(txtContentNode);
							tmpDEElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(iGroupNumber));
							tmpDEElement.setAttribute("ElementNumber","0x"+Integer.toHexString(iElementNumber));
							tmpDEElement.setAttribute("Length", Integer.toString(objIDicomValue.getValueLength()));
							tmpDEElement.setAttribute("VRType",StandardMethods.getStrVRtype(objIDicomValue.getIVRType()));
						}					
						tempITEMElement.appendChild(tmpDEElement);
						tmpDEElement = null;
					}
				}
				else
				{
					serialzeSequence(dom,tempITEMElement,objDataElement);
				}				
			}		
			if(null != tempITEMElement)
				tempSQElement.appendChild(tempITEMElement);
		}		
		if(tempITEMElement!= null)
			eleHeader.appendChild(tempSQElement);
	}



	private void serializeImageElement(Document dom, Element eleHeader,IDataElement objDataElement,IDictionaryReader objDictionaryReader) throws IOException
	{
		IDicomValue objIDicomValue = objDataElement.getDicomValue();
		Element tempImageElement = dom.createElement("ImageElement");	
		int iGroupNumber = objDataElement.getTag().getGroupNumber();
		int iElementNumber = objDataElement.getTag().getElementNumber();
		tempImageElement.setAttribute("GroupNumber", "0x"+Integer.toHexString(iGroupNumber));
		tempImageElement.setAttribute("ElementNumber","0x"+Integer.toHexString(iElementNumber));
		tempImageElement.setAttribute("Length", Integer.toString(objIDicomValue.getValueLength()));
		tempImageElement.setAttribute("VRType",StandardMethods.getStrVRtype(objIDicomValue.getIVRType()));

		String strDEDescription =null;
		Element tmpPixelElement = null;
		Text txtContentNode= null;

		strDEDescription = objDictionaryReader.getName(iGroupNumber, iElementNumber);

		if(null != strDEDescription)
		{
			strDEDescription = strDEDescription.replaceAll("\\p{Space}","");
			strDEDescription = strDEDescription.replaceAll("\\p{Punct}","");
		}
		else
			strDEDescription = "Private";

		tmpPixelElement = dom.createElement(strDEDescription);
		txtContentNode = dom.createTextNode("hidden");
		tmpPixelElement.appendChild(txtContentNode);
		tempImageElement.appendChild(tmpPixelElement);

		eleHeader.appendChild(tempImageElement);
	}




	//		// Append Image Pixel Data
	//
	//		if(objIDicomValue instanceof OB || objIDicomValue instanceof OW)
	//		{		
	//			ISingleCollection<byte[]> barray =(ISingleCollection<byte[]>)objIDicomValue.getValue();
	//
	//			if(barray != null)
	//			{
	//				for (byte[] bs : barray) 
	//				{
	//					tmpPixelElement = dom.createElement(strDEDescription);	
	//					txtContentNode = dom.createTextNode(new String(new Base64().encode(bs)));
	//					tmpPixelElement.appendChild(txtContentNode);
	//					tempImageElement.appendChild(tmpPixelElement);
	//				}
	//			}
	//			else
	//			{
	//				tmpPixelElement = dom.createElement(strDEDescription);	
	//				tempImageElement.appendChild(tmpPixelElement);
	//			}
	//
	//		}
	//		else if (objIDicomValue instanceof OBImageObject) 
	//		{
	//			OBImageObject objImageObject = (OBImageObject)objIDicomValue;
	//			int iframes = objImageObject.getNumberOfFrame();
	//
	//			for (int index = 1; index <= iframes; index++)
	//			{
	//				tmpPixelElement = dom.createElement(strDEDescription);	
	//				txtContentNode = dom.createTextNode(new String(new Base64().encode(objImageObject.getFrame(index))));
	//				tmpPixelElement.appendChild(txtContentNode);
	//				tempImageElement.appendChild(tmpPixelElement);
	//			}	
	//		}
	//
	//		else if (objIDicomValue instanceof OWImageObject) 
	//		{
	//			OWImageObject objImageObject = (OWImageObject)objIDicomValue;
	//			int iframes = objImageObject.getNumberOfFrame();
	//
	//			for (int index = 1; index <= iframes; index++)
	//			{
	//				tmpPixelElement = dom.createElement(strDEDescription);	
	//				txtContentNode = dom.createTextNode(new String(new Base64().encode(objImageObject.getFrame(index))));
	//				tmpPixelElement.appendChild(txtContentNode);
	//				tempImageElement.appendChild(tmpPixelElement);
	//			}	
	//		}
	//		eleHeader.appendChild(tempImageElement);



	//
	//	public IDataSet parseDataSet(String strXMLDicomFilePath)
	//	{
	//		IDataSet objDataSet = null;
	//		try 
	//		{
	//
	//			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	//			DocumentBuilder loader = factory.newDocumentBuilder();	
	//			Document document = loader.parse(strXMLDicomFilePath);
	//			NodeList objDocumentNodeList = document.getDocumentElement().getChildNodes();
	//
	//			//Parse Header
	//			Node objTransferSyntaxUID = objDocumentNodeList.item(0).getChildNodes().item(0);
	//			ITransferSyntax objTransferSyntax = new TransferSyntax(objTransferSyntaxUID.getTextContent());
	//			objDataSet = new DataSet(objTransferSyntax);
	//
	//			// Parse Dicom DataSet 
	//			NodeList objNodeList = objDocumentNodeList.item(1).getChildNodes();
	//
	//			Node tmpNode = null;
	//			int iGroupNumber,iElementNumber;
	//			NamedNodeMap objNamedNodeMap;
	//			int iVRType;
	//
	//
	//			for (int s = 0; s < objNodeList.getLength(); s++)
	//			{
	//				tmpNode = objNodeList.item(s);
	//
	//				if(tmpNode.getNodeName().equals("ImageElement"))
	//				{
	//					objDataSet.addDataElement(parseImageElement(tmpNode,objDataSet.getDictionaryReader(),objDataSet.getTransferSyntax()));
	//					continue;
	//				}
	//				else
	//				{		    		
	//					objNamedNodeMap = tmpNode.getAttributes();
	//					iElementNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("ElementNumber").getNodeValue().replace("0x",""), 16).intValue();    	
	//					iGroupNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("GroupNumber").getNodeValue().replace("0x",""), 16).intValue();  	
	//					iVRType = StandardMethods.getiVRtype(objNamedNodeMap.getNamedItem("VRType").getNodeValue());
	//
	//					if(iVRType == DicomConstants.DCM_DT_SQ || tmpNode.getNodeName().equals("SQ"))
	//					{
	//						objDataSet.addDataElement(parseSequence(tmpNode,iGroupNumber,iElementNumber,objDataSet.getDictionaryReader(),objDataSet.getTransferSyntax()));
	//					}
	//					else
	//						objDataSet.addDataElement(DataTypeConvertor.stringtoDataElement(tmpNode.getTextContent(), iGroupNumber, iElementNumber, iVRType, objDataSet.getTransferSyntax(), objDataSet.getDictionaryReader()));
	//				}
	//
	//			}
	//
	//
	//		} 
	//		catch (ParserConfigurationException e) 
	//		{
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//		}	
	//		catch (SAXException e)
	//		{
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//		} catch (IOException e) {
	//			// TODO Auto-generated catch block
	//			e.printStackTrace();
	//		}
	//		return objDataSet;
	//	}
	//
	//	private IDataElement parseSequence(Node objSQNode, int iSQGroupNumber, int iSQElementNumber,IDictionaryReader objDictionaryReader,ITransferSyntax objTransferSyntax)
	//	{
	//		IDataElement objIDataElement = null;
	//		IDataTypeSQ objSQ = DicomV3Factory.createInstance().createSequence(iSQGroupNumber, iSQElementNumber, objTransferSyntax);
	//
	//		Node objItemNode = null,objDENode = null;		
	//		NamedNodeMap objNamedNodeMap;
	//		int iVRType,iGroupNumber,iElementNumber;
	//		IItem objSQItem;
	//		NodeList objDataElementNodeList;
	//
	//		NodeList objItemNodeList = objSQNode.getChildNodes();
	//		for (int iItemCount = 0; iItemCount < objItemNodeList.getLength(); iItemCount++)
	//		{			
	//			objItemNode = objItemNodeList.item(iItemCount);			
	//			objSQItem = objSQ.getNewItem();			
	//			objDataElementNodeList = objItemNode.getChildNodes();
	//			for (int iDECount = 0; iDECount < objDataElementNodeList.getLength(); iDECount++)
	//			{
	//				objDENode = objDataElementNodeList.item(iDECount);
	//
	//				if(objDENode.getNodeName().equals("ImageElement"))
	//				{
	//					objSQItem.addDataElement(parseImageElement(objDENode,objDictionaryReader,objTransferSyntax));
	//					continue;
	//				}
	//				else
	//				{		    		
	//					objNamedNodeMap = objDENode.getAttributes();
	//					iElementNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("ElementNumber").getNodeValue().replace("0x",""), 16).intValue();    	
	//					iGroupNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("GroupNumber").getNodeValue().replace("0x",""), 16).intValue();		    	
	//					iVRType =  StandardMethods.getiVRtype(objNamedNodeMap.getNamedItem("VRType").getNodeValue());
	//
	//					if(iVRType == DicomConstants.DCM_DT_SQ)
	//					{
	//						objSQItem.addDataElement(parseSequence(objDENode,iGroupNumber,iElementNumber,objDictionaryReader,objTransferSyntax));
	//					}
	//					else
	//						objSQItem.addDataElement(DataTypeConvertor.stringtoDataElement(objDENode.getTextContent(), iGroupNumber, iElementNumber, iVRType,objTransferSyntax,objDictionaryReader));
	//				}
	//			}			
	//			objSQ.addItem(objSQItem);
	//		}
	//
	//		if(objTransferSyntax.getVRTransferSyntax()==DicomConstants.DCM_VR_IMPLICIT)
	//			objIDataElement = new ImplicitDE(iSQGroupNumber, iSQElementNumber,objSQ,objSQ.getTransferSyntax(),objDictionaryReader);
	//		else
	//			objIDataElement = new ExplicitDE(iSQGroupNumber,iSQElementNumber,DicomConstants.DCM_DT_SQ,objSQ);
	//
	//		return objIDataElement;
	//	}
	//
	//	private IDataElement parseImageElement(Node objImageElementNode, IDictionaryReader objDictionaryReader, ITransferSyntax objTransferSyntax)
	//	{
	//		IDataElement objIDataElement = null;
	//		IDicomValue objDicomValue = null;
	//		NamedNodeMap objNamedNodeMap = objImageElementNode.getAttributes();
	//		int	iElementNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("ElementNumber").getNodeValue().replace("0x",""), 16).intValue();    	
	//		int	iGroupNumber = Integer.valueOf(objNamedNodeMap.getNamedItem("GroupNumber").getNodeValue().replace("0x",""), 16).intValue();   	
	//		int iVRType = StandardMethods.getiVRtype(objNamedNodeMap.getNamedItem("VRType").getNodeValue());
	//		int iLength = Integer.parseInt(objNamedNodeMap.getNamedItem("Length").getNodeValue());	
	//
	//
	//		if(iVRType == DicomConstants.DCM_DT_UN)
	//		{
	//			byte[] objByteArray = new Base64().decode(objImageElementNode.getTextContent().getBytes());
	//			objDicomValue =	DicomV3Factory.createInstance().createDataType(iVRType);
	//			objDicomValue.setValue(objByteArray);
	//		}
	//		else	
	//		{
	//			ISingleCollection<byte[]> objImageDataSingleCollection = new SingleCollection<byte[]>();
	//
	//			NodeList objImageDataNodeList = objImageElementNode.getChildNodes();
	//			for (int iImageFrameCount = 0; iImageFrameCount < objImageDataNodeList.getLength(); iImageFrameCount++)
	//			{
	//				objImageDataSingleCollection.add(new Base64().decode(objImageDataNodeList.item(iImageFrameCount).getTextContent().getBytes()));
	//			}
	//
	//			if(iVRType == DicomConstants.DCM_DT_OB || iVRType == DicomConstants.DCM_DT_OW)
	//			{
	//				objDicomValue =	DicomV3Factory.createInstance().createDataType(iVRType);
	//				objDicomValue.setValue(objImageDataSingleCollection);
	//				if(iLength == DicomConstants.DCM_UNDEFINED_LENGTH)
	//				{
	//					if(objDicomValue instanceof OB)
	//						((OB)objDicomValue).changeToUndefined();
	//					else 
	//						((OW)objDicomValue).changeToUndefined();						
	//				}
	//			}	
	//		}
	//		if(objTransferSyntax.getVRTransferSyntax()==DicomConstants.DCM_VR_IMPLICIT)
	//			objIDataElement = new ImplicitDE(iGroupNumber, iElementNumber,objDicomValue,objTransferSyntax,objDictionaryReader);
	//		else
	//			objIDataElement = new ExplicitDE(iGroupNumber,iElementNumber,iVRType,objDicomValue);
	//
	//		return objIDataElement;
	//	}	
}
