/*******************************************************************************
 *  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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Locale;

import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataElement;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomValue;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDicomStream;
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.dicomstreams.DicomBufferStream;
import cdac.medinfo.sdk.dcm30_04.dictionaryreaderwriters.DictionaryReader;
import cdac.medinfo.sdk.dcm30_04.enums.EnumLoggingLevel;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidDataElementException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidDataSetException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidDataTypeException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidItemException;
import cdac.medinfo.sdk.dcm30_04.exceptions.ParseException;
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.GlobalConstants;
import cdac.medinfo.sdk.dcm30_04.utils.ICollectionIterator;
import cdac.medinfo.sdk.dcm30_04.utils.IPairedCollection;
import cdac.medinfo.sdk.dcm30_04.utils.PairedCollection;
import cdac.medinfo.sdk.dcm30_04.utils.ResourceBundleWrapper;

/** 
 * An Item contains a Data Set.
 * Item in short is the  component of the Value of a Data Element that is of Value Representation Sequence of Items.
 */
public class Item implements IItem  
{
	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1L;

	IDataElement current,prev ;
	boolean bItemDelimitationExpected;
	ITransferSyntax objITransferSyntax;
	boolean isUndefinedLength;

	IPairedCollection<ITag, IDataElement> objPairedCollection = null;

	/*
	 * 	This DictionaryReader object would be used to hold 
	 * 	the Dictionary Reference.This reference will be get from 
	 * 	SQ and used by Implicit DataElement.
	 */
	IDictionaryReader objIDictionaryReader = null;

	/**
	 * This constructor creates SQ with default TransferSyntax 
	 */
	public Item()
	{
		this(new TransferSyntax(),DictionaryReader.createInstance());

	}

	/*
	 * This constructor should throw exception if TS is tried to be set as null
	 */
	/**
	 * This constructor creates SQ with specified TransferSyntax
	 * @param objTransferSyntax TransferSyntax specified by DICOM Standard
	 */
	public Item(ITransferSyntax objTransferSyntax)
	{
		bItemDelimitationExpected = false;
		objITransferSyntax = objTransferSyntax;
		objPairedCollection = new PairedCollection<ITag,IDataElement>();
	}

	/*
	 * This constructor internally calls other constructor which actually does the task
	 * This constructor should throw exception if dictionaryreader is tried to be set as null
	 */
	/**
	 * This constructor creates SQ with default TransferSyntax and specified DictionaryReader
	 * @param objDictionaryReader DictionaryReader specifies the reader specified by user
	 * 								which will read from dictionary	
	 */
	public Item(IDictionaryReader objDictionaryReader)
	{
		this(new TransferSyntax(),objDictionaryReader);
	}

	/*
	 * This constructor should throw exception if TS or dictionaryreader is tried to be set as null 
	 */
	/**
	 * This constructor creates SQ with specified transferSyntax and specified DictionaryReader
	 * @param objTransferSyntax TransferSyntax specified by DICOM Standard
	 * @param objDictionaryReader DictionaryReader specifies the reader specified by user
	 * 								which will read from dictionary	
	 */
	public Item(ITransferSyntax objTransferSyntax,IDictionaryReader objDictionaryReader)
	{
		bItemDelimitationExpected = false;
		objITransferSyntax = objTransferSyntax;
		objIDictionaryReader = objDictionaryReader;
		objPairedCollection = new PairedCollection<ITag,IDataElement>();
	}

	/**
	 * This method provides a mechanism to set the item length when the item value length is provided.
	 * @param iItemValueLength length of the value of the item which excludes the Item major and minor tags
	 */
	public int getItemLength()
	{
		int iFullItemLength = 0;
		if(isUndefinedLength == true)
		{
			return DicomConstants.DCM_UNDEFINED_LENGTH;
		}
		else
		{
			iFullItemLength= 4+4+getValueLength();
		}
		return iFullItemLength;
	}

	/**
	 * Retrieves the value length of the item. Note that this length excludes the Item major and minor tags 
	 * @return integer - value length of the item
	 */
	public int getValueLength()
	{
		int iItemValueLength = 0;
		if(isUndefinedLength == true)
		{
			return DicomConstants.DCM_UNDEFINED_LENGTH;
		}
		else
		{
			ICollectionIterator<IDataElement> objDataElementIterator = iterator();
			while(objDataElementIterator.hasNext())
			{
				IDataElement objIDataElement = objDataElementIterator.next();
				if(objIDataElement.getDataElementLength() == DicomConstants.DCM_UNDEFINED_LENGTH)
				{
					return DicomConstants.DCM_UNDEFINED_LENGTH;
				}
				iItemValueLength = iItemValueLength + objIDataElement.getDataElementLength();
			}
		}
		return iItemValueLength;
	}

	/**
	 * Sets the TransferSyntax specified by DICOM Standard
	 * @param objITransferSyntax  TransferSyntax specified by DICOM Standard
	 */
	public void setTransferSyntax(ITransferSyntax objITransferSyntax)
	{
		this.objITransferSyntax =objITransferSyntax; 
	}

	/*
	 * (non-Javadoc) This method return the TransferSyntax set the Item
	 * @see cdac.medinfo.sdk.dcm30_04.commoninterface.IItem#getTransferSyntax()
	 */
	/**
	 * Retrieves the TransferSyntax specified by DICO  Standard
	 * @return TrabsferSyntax - TransferSyntax specified by DICOM Standard 
	 */
	public ITransferSyntax getTransferSyntax()
	{
		return objITransferSyntax;
	}
	/**
	 * This method adds DataElement into the Item of SQ
	 * @param objIDataElement Object of dataelement to add
	 * @return int - status indicating success/failure
	 */
	public int addDataElement(IDataElement objIDataElement)
	{
		objPairedCollection.put(objIDataElement.getTag(),objIDataElement);
		return 1;
	}

	/**
	 * Sets the DictionaryReader into the Item
	 * @param objIDictReader object of Dictionary Reader to be used by the Item 
	 */
	public void setDictionaryReader(IDictionaryReader objIDictReader)
	{
		objIDictionaryReader =  objIDictReader;
	}

	/**
	 * Retrieves the Dictionary reader set in the Item
	 * @return IDictionaryReader - DictionaryReader set in the Item
	 */
	public IDictionaryReader getDictionaryReader()
	{
		return objIDictionaryReader;
	}

	/**
	 * Reads the Item from the underlying stream as specified in the DICOM Standard
	 * @param objIDicomStream stream from which the Item is to be written
	 * @param iItemLength length of the DicomValue to be read from the stream
	 * @return integer - returns status success/failure
	 * @throws InvalidItemException Signals Item Validation is failed.
	 * @throws IOException Signals that an I/O exception of some sort has occurred.
	 */
	public int read(IDicomStream objIDicomStream, int iItemLength) throws InvalidItemException, IOException
	{
		try
		{
			int prevGroupNumber,prevElementNumber;

			int iBeforeItemReading = objIDicomStream.getReadBytes();
			int iAfterEachElementReading = 0;

			if(iItemLength == DicomConstants.DCM_UNDEFINED_LENGTH)
			{
				isUndefinedLength = true;
			}

			if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_EXPLICIT)
			{
				int iItemDelimitation = 0;
				while(true)
				{
					//ExplicitDE Class constructor has default scope.
					//Its object can be created using DicomV3Factory				
					current = new ExplicitDE();
					//TransferSyntax of DataElement in Item should be same as that of Item
					current.setTransferSyntax(objITransferSyntax);

					iItemDelimitation = current.parse(objIDicomStream);
					if(DicomConstants.DCM_UNDEFINED_LENGTH == iItemLength)
					{
						if(iItemDelimitation == GlobalConstants.DCM_ITEM_DELIMITATION)
							break;
					}
					else
					{
						iAfterEachElementReading = objIDicomStream.getReadBytes();
						if(iItemLength == (iAfterEachElementReading - iBeforeItemReading) )
						{
							if(prev != null)
							{
								prevGroupNumber = prev.getTag().getGroupNumber();
								prevElementNumber = prev.getTag().getElementNumber();
								if(prevGroupNumber > current.getTag().getGroupNumber())
								{
									if(DicomConfig.createInstance().isLoggingOn())
									{
										DicomLogger objDicomLogger = DicomLogger.getLogger();
										objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
									}						
								}	
							if(prevGroupNumber  == current.getTag().getGroupNumber()&& prevElementNumber > current.getTag().getElementNumber())
							{
								if(DicomConfig.createInstance().isLoggingOn())
								{
									DicomLogger objDicomLogger = DicomLogger.getLogger();
									objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
								}
							}
							}
							objPairedCollection.put(current.getTag(), current);
							prev = current;	
							break;
						}
					}
					if(prev != null)
					{
						prevGroupNumber = prev.getTag().getGroupNumber();
						prevElementNumber = prev.getTag().getElementNumber();
						if(prevGroupNumber > current.getTag().getGroupNumber())
						{
							if(DicomConfig.createInstance().isLoggingOn())
							{
								DicomLogger objDicomLogger = DicomLogger.getLogger();
								objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
							}
						}
							if(prevGroupNumber  == current.getTag().getGroupNumber()&& prevElementNumber > current.getTag().getElementNumber())
							{
								if(DicomConfig.createInstance().isLoggingOn())
								{
									DicomLogger objDicomLogger = DicomLogger.getLogger();
									objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
								}	
							}
							}
					objPairedCollection.put(current.getTag(), current);
					prev = current;	
				}
			}
			if(objITransferSyntax.getVRTransferSyntax() == DicomConstants.DCM_VR_IMPLICIT)
			{
				int iItemDelimitation = 0;
				while(true)
				{
					//By Atreya,ImplicitDE Class constructor has default scope.
					//Its object can be created using DicomV3Factory
					current = new ImplicitDE(getDictionaryReader());

					//Sets the TransferSyntax to the DataElement
					current.setTransferSyntax(objITransferSyntax);
					//Sets the DictionaryReader object
					//This is needed since in the prasing scenario of a SQ,suppose the Item
					//contains one Implicit DataElement. This data element needs the 
					//DictionaryReader object to get the VR. Hence,we set that dcitionary reader 
					//reference here.

					iItemDelimitation = current.parse(objIDicomStream);
					if(DicomConstants.DCM_UNDEFINED_LENGTH == iItemLength)
					{
						if(iItemDelimitation == GlobalConstants.DCM_ITEM_DELIMITATION)
							break;
					}
					else
					{
						iAfterEachElementReading = objIDicomStream.getReadBytes();
						if(iItemLength == (iAfterEachElementReading - iBeforeItemReading) )
						{
							if(prev != null)
							{
								prevGroupNumber = prev.getTag().getGroupNumber();
								prevElementNumber = prev.getTag().getElementNumber();
								if(prevGroupNumber > current.getTag().getGroupNumber())
								{
									if(DicomConfig.createInstance().isLoggingOn())
									{
										DicomLogger objDicomLogger = DicomLogger.getLogger();
										objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
									}
								}
									if(prevGroupNumber  == current.getTag().getGroupNumber()&& prevElementNumber > current.getTag().getElementNumber())
									{
										if(DicomConfig.createInstance().isLoggingOn())
										{
											DicomLogger objDicomLogger = DicomLogger.getLogger();
											objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
										}	
									}
								}
							objPairedCollection.put(current.getTag(), current);
							prev = current;	
							break;
						}
					}
					if(prev != null)
					{
						prevGroupNumber = prev.getTag().getGroupNumber();
						prevElementNumber = prev.getTag().getElementNumber();
						if(prevGroupNumber > current.getTag().getGroupNumber())
						{
							if(DicomConfig.createInstance().isLoggingOn())
							{
								DicomLogger objDicomLogger = DicomLogger.getLogger();
								objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
							}
						}
						if(prevGroupNumber  == current.getTag().getGroupNumber()&& prevElementNumber > current.getTag().getElementNumber())
						{
							if(DicomConfig.createInstance().isLoggingOn())
							{
								DicomLogger objDicomLogger = DicomLogger.getLogger();
								objDicomLogger.log(ResourceBundleWrapper.getValue("warning","InvalidOrder",new Locale(DicomConfig.createInstance().getLocale()))+ current.getTag().getGroupNumber() + "," + current.getTag().getElementNumber());
							}	
						}
					}
					objPairedCollection.put(current.getTag(), current);
					prev = current;	
				}
			}
		}
		catch( InvalidDataTypeException de)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(de.getMessage());
			}
			throw new InvalidItemException(this.getClass().getSimpleName());
		}
		catch( ParseException pe)
		{
			if(DicomConfig.createInstance().isLoggingOn())
			{
				DicomLogger.getLogger().log(pe.getMessage());
			}
			if(DicomConfig.createInstance().isLoggingOn()&&(DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.INFO))
			{
				DicomBufferStream objBuffStream = new DicomBufferStream();
				ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
				objBuffStream.setOutputStream(objByteArrayOutputStream);
				this.write(objBuffStream);
				String strLogMessage = objBuffStream.toString();
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(strLogMessage);
				objDicomLogger.log(pe);
			}
			else if(DicomConfig.createInstance().isLoggingOn()&&(DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.SEVERE))
			{
				DicomLogger objDicomLogger = DicomLogger.getLogger();	
				objDicomLogger.log(pe);
			}

		}
		return 1;
	}

	/**
	 * Get the DataElements from the HashMap and call serialize on each
	 * dataelement individually. At the last check if the iItemLength
	 * is UNDEFINED,if it is,then write the Item Delemitation Tag and
	 * 4 bytes Zero Length onto the Stream after all the elements are written.
	 * @param objIDicomStream  stream on which to write the DataElements
	 * @return integer - status indicating success/failure
	 * @throws IOException  Signals that an I/O exception of some sort has occurred.
	 */
	public int write(IDicomStream objIDicomStream) throws IOException
	{
		ICollectionIterator<IDataElement> objItemIterator = objPairedCollection.sortedIterator();
		//Get each Element from the HashMap and serialize it to stream
		objIDicomStream.writeShort((short)DicomConstants.DCM_NESTED_ITEM_DATA_MAJOR_TAG);
		objIDicomStream.writeShort((short)DicomConstants.DCM_NESTED_ITEM_DATA_MINOR_TAG);

		objIDicomStream.writeInt(getValueLength());
		while(objItemIterator.hasNext())
		{
			objItemIterator.next().serialize(objIDicomStream);
		}
		if(DicomConstants.DCM_UNDEFINED_LENGTH == getItemLength())
		{
			IDataElement objIDataElement = new ImplicitDE(getDictionaryReader());
			objIDataElement.setTag(DicomConstants.DCM_NESTED_ITEM_DELIMITATION_DATA_MAJOR_TAG, DicomConstants.DCM_NESTED_ITEM_DELIMITATION_DATA_MINOR_TAG);
			//Write the Item Delemitation Tag and 4 bytes zero length as int 
			objIDataElement.serialize(objIDicomStream);
		}
		return 1;
	}

	/**
	 * Provides iterator over the collection of DataElements
	 * @return Iterator - custom iterator over the collection of DataElements
	 */
	public ICollectionIterator<IDataElement> iterator()
	{
		return objPairedCollection.sortedIterator();
	}

	/**
	 * Provides sorted iterator over the collection of DataElements
	 * @return Iterator - custom iterator over the collection of DataElements in sorted order.
	 */
	public ICollectionIterator<IDataElement> sortedIterator()
	{
		return objPairedCollection.iterator();
	}

	/**
	 * Retrieves the DataElement for the specified Group and Element numbers
	 * @param iGroupNumber specifies the Group Number.
	 * @param iElementNumber specifies the Element Number.
	 * @return IDataElement - object of DataElement retreived from the item collection.
	 */
	public IDataElement getDataForTag(int iGroupNumber, int iElementNumber)
	{
		if(contains(iGroupNumber, iElementNumber))
			return objPairedCollection.get(new Tag(iGroupNumber,iElementNumber));
		return null;
	}

	/**
	 * Checks whether the DataElement with the specified Group and Element numbers is present or not
	 * @param iGroupNumber specifies the Group Number.
	 * @param iElementNumber specifies the Element Number.
	 * @return boolean - shows status as success or failure.
	 */
	public boolean contains(int iGroupNumber, int iElementNumber)
	{
		return objPairedCollection.contains(new Tag(iGroupNumber,iElementNumber));
	}

	/**
	 * Validates the Item for the rules of module. Specific modules are expected to override the validation method
	 * @return boolean - status indicating success/failure
	 * @throws InvalidItemException Signals Item Validation is failed.
	 */
	public boolean validateForModule() throws InvalidItemException
	{
		return true;
	}

	/**
	 * Validates the Item for the rules of module. Specific modules are expected to override the validation method
	 * @return boolean - status indicating success/failure
	 * @throws InvalidItemException Signals Item Validation is failed.
	 */
	public boolean validate() throws InvalidItemException
	{
		for(IDataElement objIDataElement : objPairedCollection)
		{
			try
			{
				if(objIDataElement!= null)
					objIDataElement.validate();
			}
			catch( InvalidDataElementException ide)
			{
				if(DicomConfig.createInstance().isLoggingOn())
				{
					DicomLogger.getLogger().log(ide.getMessage());
				}
				
				throw new InvalidDataSetException(ide.getMessage(),ide);
			}
		}
		return true;
	}
	/**
	 * Sets the custom paired collection of tag and DataElement into the Item
	 * @param objPairedCollection_  paired collection of Tag and DataElement representing the collection of DataElements	
	 * @return int - shows status as success or failure.
	 * @throws InvalidItemException Signals Item Validation is failed.
	 */
	public int setValue(IPairedCollection<ITag, IDataElement> objPairedCollection_) throws InvalidItemException
	{
		try
		{
			objPairedCollection = objPairedCollection_;
			validateForModule();
		}
		catch(InvalidItemException iie)
		{

				throw iie;
		}
		return 1;
	}

	/**
	 * This method returns value of DicomValue.
	 * @param GroupNumber Group Number of the DataElement
	 * @param ElementNumber  Element Number of the DataElement
	 * @return Object - instance of IDicomValue.
	 */
	public Object getValue(int iGroupNumber, int iElementNumber)
	{
		IDataElement objIDataElement =  getDataForTag(iGroupNumber,iElementNumber);
		if(objIDataElement == null)
			return null;
		IDicomValue objIDicomValue = objIDataElement.getDicomValue();
		if(objIDicomValue == null)
			return null;
		return objIDicomValue.getValue();
	}

	/**
	 * Create similar object of this class.
	 * This does the deep copy and create a new instance of this class nad return it.
	 * @return a clone of this instance.
	 */
	public Object clone()
	{
		try
		{			
			ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();     
			ObjectOutputStream objObjectOutputStream = new ObjectOutputStream(objByteArrayOutputStream);         

			objObjectOutputStream.writeObject(this);
			objObjectOutputStream.flush();
			objObjectOutputStream.close();

			ObjectInputStream objObjectInputStream = new ObjectInputStream(new ByteArrayInputStream(objByteArrayOutputStream.toByteArray()));
			Item objItem = (Item)objObjectInputStream.readObject();

			return objItem;
		}
		catch (IOException ioe) 
		{
			if(DicomConfig.createInstance().isLoggingOn() && DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.SEVERE)
			{
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(ioe.getMessage());
			}
			else if (DicomConfig.createInstance().isLoggingOn() && DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.INFO) 
			{
				DicomBufferStream objBuffStream = new DicomBufferStream();
				ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
				objBuffStream.setOutputStream(objByteArrayOutputStream);
				try
				{
					this.write(objBuffStream);
				} 
				catch (IOException e) {}
				String strLogMessage = objBuffStream.toString();
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(strLogMessage);
				objDicomLogger.log(ioe.getMessage());
			}
		}
		catch (ClassNotFoundException e)
		{
			if(DicomConfig.createInstance().isLoggingOn() && DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.SEVERE)
			{
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(e.getMessage());
			}
			else if (DicomConfig.createInstance().isLoggingOn() && DicomConfig.createInstance().getLoggingLevel() == EnumLoggingLevel.INFO) 
			{
				DicomBufferStream objBuffStream = new DicomBufferStream();
				ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
				objBuffStream.setOutputStream(objByteArrayOutputStream);
				try
				{
					this.write(objBuffStream);
				}
				catch (IOException e1) {}
				String strLogMessage = objBuffStream.toString();
				DicomLogger objDicomLogger = DicomLogger.getLogger();
				objDicomLogger.log(strLogMessage);
				objDicomLogger.log(e.getMessage());
			}
		}
		return null;
	}

	/**
	 *  Dumps the Items of Sequence in readable form.
	 *  @param objIDicomStream - the Stream on which the Data is to be written.
	 *  @throws IOException - Exception is thrown indicating runtime failure of writing operation.
	 */
	public void dumpDICOMInfo(IDicomStream objIDicomStream) throws IOException
	{
		for(IDataElement objIDataElement : objPairedCollection)
		{
			objIDicomStream.writeString("\t>");
			objIDataElement.dumpDICOMInfo(objIDicomStream);
			objIDicomStream.writeString("\n");
		}
	}

	/**
	 * This function sets the Value length to -1.
	 * If this function is called then then length of value is undefined length(-1)
	 */
	public void changeToUndefined()
	{
		this.isUndefinedLength = true;
	}
}