/*******************************************************************************
 *  Copyright 2017 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.hl7282.baselibs.segments;

import java.io.IOException;
import java.util.Locale;

import cdac.medinfo.sdk.hl7282.baselibs.DTM;
import cdac.medinfo.sdk.hl7282.baselibs.HD;
import cdac.medinfo.sdk.hl7282.baselibs.ST;
import cdac.medinfo.sdk.hl7282.commoninterface.IDataType;
import cdac.medinfo.sdk.hl7282.commoninterface.IDelimiter;
import cdac.medinfo.sdk.hl7282.commoninterface.IHL7Stream;
import cdac.medinfo.sdk.hl7282.commoninterface.ISingleCollection;
import cdac.medinfo.sdk.hl7282.exceptions.DelimiterMissingException;
import cdac.medinfo.sdk.hl7282.exceptions.FieldMissingException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidDataTypeException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidDelimiterException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidFieldException;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidSegmentException;
import cdac.medinfo.sdk.hl7282.exceptions.SerializeException;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.HL7Config;
import cdac.medinfo.sdk.hl7282.utils.HL7Constants;
import cdac.medinfo.sdk.hl7282.utils.ResourceBundleWrapper;

/**
 * FHS - File header segment <p>
 * The FHS segment defines the intent, source, destination, and some specifics of the
 * syntax of a File.
 * <p>Represents an HL7 FHS File header segment. 
 * This segment has the following fields:</p><p>
 * FHS-1: Field Separator (ST)<b>Required</b><br> 
 * FHS-2: Encoding Characters (ST)<b>Required</b><br> 
 * FHS-3: Sending Application (HD)<b>Optional</b><br> 
 * FHS-4: Sending Facility (HD)<b>Optional</b><br> 
 * FHS-5: Receiving Application (HD)<b>Optional</b><br> 
 * FHS-6: Receiving Facility (HD)<b>Optional</b><br> 
 * FHS-7: Date/Time Of File (DTM)<b>Optional</b><br> 
 * FHS-8: File Security (ST)<b>Optional</b><br> 
 * FHS-9: File Type (ST)<b>Optional</b><br> 
 * FHS-10: File Comment (ST)<b>Optional</b><br> 
 * FHS-11: File Control ID (ST)<b>Optional</b><br> 
 * FHS-12: Reference File Control ID (ST)<b>Optional</b><br> 
 * FHS-13: File Sending Network Address (HD)<b>Optional</b><br> 
 * FHS-14: File Receiving Network Address (HD)<b>Optional</b><br> 
 * </p>
 * This class provides mechanism to validate message against HL7 v 2.8.2 standard.
 * The class provides accessors & mutators for the elements mentioned above.
 * The class has validate method which validates Message against HL7 v 2.8.2 standard.
 *
 * <p>User can also create Segment through {@link SegmentFactory}
 */
 public class FHS extends Segment   
{
	


	protected Delimiter objDelimiter;

	/**
	 * Constructs the FHS segment.
	 */
	public FHS()
	{
		super(EnumSegments.HL7_SEG_FHS);
		objDelimiter = new Delimiter();
	}
	//Integer values used in getter/setter is unique item id defined 
	//for each attribute.

	/**
	 * Retrieves the Delimiter.
	 * @return IDelimiter - delimiter.
	 */	
	public IDelimiter getDelimiter()
	{
		return objDelimiter;
	}

	/**
	 * Retrieves the Date Time Of File.
	 * This field contains the date/time that the sending system created the File.
	 * @return DTM - dateTimeOfFile
	 */
	public DTM getDateTimeOfFile() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(73);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (DTM)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Encoding Char.
	 * This field contains the four characters in the following order: the 
	 * component separator, repetition separator, escape character, and subcomponent separator.
	 * @return ST - encodingChar
	 */
	public ST getEncodingChar() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(68);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Field Separator.
	 * This field contains the separator between the segment ID and the first real field.
	 * @return ST - fieldSeparator
	 */
	public ST getFieldSeparator() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(67);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @return ST - FileControlID
	 */
	public ST getFileControlID() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(77);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}


	/**
	 * Retrieves the Receiving Application.
	 * Identifier of the network location the message was transmitted from.  
	 * @return HD - receivingApplication
	 */
	public HD getReceivingApplication() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(71);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Receiving Facility.
	 * This field identify the receiving application among multiple identical instances of 
	 * the application running on behalf of different organizations. 
	 * @return HD - receivingFacility
	 */
	public HD getReceivingFacility() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(72);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Security.
	 * @return ST - security
	 */
	public ST getSecurity() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(74);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Sending Application.
	 * This field uniquely identifies the sending application among all other applications within the network enterprise.
	 * @return HD - sendingApplication
	 */
	public HD getSendingApplication() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(69);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Sending Facility.
	 * This field used as the HL7 identifier for the user-defined table of values for the first component.
	 * @return HD - sendingFacility
	 */
	public HD getSendingFacility() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(70);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}



	/**
	 * Retrieves the File Type.
	 * This field contains the File type
	 * @return ST - FileName
	 */
	public ST getFileName() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(75);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Set the Field Separator.
	 * This field contains the separator between the segment ID and the first real field.
	 * @param cfieldSeparator Use as cfieldSeparator.
	 * @return 0.
	 */
	public void setFieldSeparator(char cfieldSeparator) 
	{
		String strFSSeparator = "" + cfieldSeparator;
		ST fieldSeparator = (ST)getDataElement(67);
		fieldSeparator.setValue(strFSSeparator);
		objDelimiter.cFieldSeparator = cfieldSeparator;
		setFieldSeparator(fieldSeparator);
	}
	/**
	 * Set the Field Separator.
	 * This field contains the separator between the segment ID and the first real field.
	 * @param objfieldSeparator object of Field Separator.
	 */
	public void setFieldSeparator(ST objfieldSeparator) 
	{ 
		String strFSSeparator;
		strFSSeparator =(String)objfieldSeparator.getValue();
		char cfieldSeparator =strFSSeparator.charAt(0);
		objDelimiter.cFieldSeparator = cfieldSeparator;
		setDataType(67,objfieldSeparator);
	}
	/**
	 * Set the Encoding Char.
	 * This field contains the four characters in the following order: the 
	 * component separator, repetition separator, escape character, and subcomponent separator.
	 * @param cComponentSeparator Delimiter Use as ComponentSeparator
	 * @param cSubComponentSeparator Delimiter Use as SubComponentSeparator
	 * @param cRepetitionSeparator Delimiter Use as RepetitionSeparator
	 * @param cEscapeCharacter Delimiter Use as EscapeCharacter
	 */
	public void setEncodingChars(char cComponentSeparator, char cSubComponentSeparator, char cRepetitionSeparator, char cEscapeCharacter, char cTruncationCharacter) 
	{
		objDelimiter.cComponentSeparator = cComponentSeparator;
		objDelimiter.cSubComponentSeparator = cSubComponentSeparator;
		objDelimiter.cRepetitionSeparator = cRepetitionSeparator;
		objDelimiter.cEscapeCharacter = cEscapeCharacter;
		objDelimiter.cTruncationCharacter=cTruncationCharacter;
		String strEncodingChar = "";
		strEncodingChar =  strEncodingChar + cComponentSeparator +cRepetitionSeparator + cEscapeCharacter + cSubComponentSeparator + cTruncationCharacter; 
		ST encodingChar = (ST)getDataElement(68);
		encodingChar.setValue(strEncodingChar);
		setEncodingChars(encodingChar);
	}
	/**
	 * Set the Encoding Char.
	 * This field contains the four characters in the following order: the
	 * component separator, repetition separator, escape character, and subcomponent separator. 
	 * @param objencodingChar object of Encoding Char.
	 */
	public void setEncodingChars(ST objencodingChar) 
	{ 
		String strEncodingChar = (String)objencodingChar.getValue();
		objDelimiter.cComponentSeparator = strEncodingChar.charAt(0);
		objDelimiter.cRepetitionSeparator = strEncodingChar.charAt(1);
		objDelimiter.cEscapeCharacter = strEncodingChar.charAt(2);
		objDelimiter.cSubComponentSeparator = strEncodingChar.charAt(3);
		objDelimiter.cTruncationCharacter = strEncodingChar.charAt(4);
		setDataType(68,objencodingChar);
	}

	/** 
	 * Set the Date Time Of File.
	 * This field contains the date/time that the sending system created the File.
	 * @param strTime Specifies a point in time using a 24-hour clock notation. 
	 */ 
	public void setdateTimeOfFile (String strTime) 
	{
		DTM dateTimeOfFile  = (DTM)getDataElement(73);
		dateTimeOfFile.setValue(strTime);
		setdateTimeOfFile(dateTimeOfFile);

	} 

	/**Sets the Date Time Of File.  
	 * @param objdateTimeOfFile object of Date Time Of File. 
	 */ 
	public void setdateTimeOfFile(DTM objdateTimeOfFile)
	{
		setDataType(73,objdateTimeOfFile);

	}
	/** 
	 * Set the File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @param strFileControlID Specifies a number or other identifier that uniquely identifies the File. 
	 */ 
	public void setFileControlID (String strFileControlID) 
	{
		ST fileControlID  = (ST)getDataElement(77);
		fileControlID.setValue(strFileControlID); 
		setFileControlID(fileControlID);

	} 

	/** Set the File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @param objfileControlID object of File Control ID.
	 */ 
	public void setFileControlID(ST objfileControlID)
	{
		setDataType(77,objfileControlID);

	}
	/** 
	 * Set the File Type.
	 * This field contains the File type  for the File.
	 * @param strFileName Specifies the File type code.
	 */ 
	public void setFileName (String strFileName) 
	{
		ST fileName  = (ST)getDataElement(75);
		fileName.setValue(strFileName); 
		setFileName(fileName);
	} 

	/** Set the File Type.
	 * This field contains the File type  for the File.
	 * @param objfileName object of File Name.
	 */ 
	public void setFileName(ST objfileName)
	{
		setDataType(75,objfileName);
	}
	/** 
	 * Set the Receiving Application.
	 * Identifier of the network location the message was transmitted from.  
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */ 
	public void setReceivingApplication (String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD receivingApplication  = (HD)getDataElement(71);
		receivingApplication.setNamespaceId(strNamespaceId);
		receivingApplication.setUniversalId(strUniversalId);
		receivingApplication.setUniversalIdType(strUniversalIdType); 
		setReceivingApplication(receivingApplication);

	} 

	/** Set the Receiving Application.
	 * Identifier of the network location the message was transmitted from.  
	 * @param objreceivingApplication object of Receiving Application. 
	 */ 
	public void setReceivingApplication(HD objreceivingApplication)
	{
		setDataType(71,objreceivingApplication);

	}
	/** 
	 * Set the Receiving Facility.
	 * This field identify the receiving application among multiple identical instances of 
	 * the application running on behalf of different organizations.
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */ 
	public void setReceivingFacility (String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD receivingFacility  = (HD)getDataElement(72);
		receivingFacility.setNamespaceId(strNamespaceId);
		receivingFacility.setUniversalId(strUniversalId);
		receivingFacility.setUniversalIdType(strUniversalIdType); 
		setReceivingFacility(receivingFacility);
	} 

	/** Set the Receiving Facility.
	 * This field identify the receiving application among multiple identical instances of 
	 * the application running on behalf of different organizations.
	 * @param objreceivingFacility object of Receiving Facility. 
	 */ 
	public void setReceivingFacility(HD objreceivingFacility)
	{
		setDataType(72,objreceivingFacility);
	}	
	/** 
	 * Set the Security.
	 * @param strSecurity Specifies a field ,that is used to implement security features. 
	 */ 
	public void setSecurity (String strSecurity) 
	{
		ST security  = (ST)getDataElement(74);
		security.setValue(strSecurity); 
		setSecurity(security);

	} 

	/** Set the Security.
	 * @param objsecurity object of Security. 
	 */ 
	public void setSecurity(ST objsecurity)
	{
		setDataType(74,objsecurity);

	}
	/** 
	 * Set the Sending Application.
	 * This field uniquely identifies the sending application among all other applications within the network enterprise.
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */ 
	public void setSendingApplication (String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD sendingApplication  = (HD)getDataElement(69);
		sendingApplication.setNamespaceId(strNamespaceId);
		sendingApplication.setUniversalId(strUniversalId);
		sendingApplication.setUniversalIdType(strUniversalIdType); 
		setSendingApplication(sendingApplication);

	} 

	/** Set the Sending Application.
	 * This field uniquely identifies the sending application among all other applications within the network enterprise.
	 * @param objsendingApplication object of Sending Application. 
	 */ 
	public void setSendingApplication(HD objsendingApplication)
	{
		setDataType(69,objsendingApplication);

	}	
	/** 
	 * Set the Sending Facility.
	 * This field used as the HL7 identifier for the user-defined table of values for the first component.
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */ 
	public void setSendingFacility (String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD sendingFacility  = (HD)getDataElement(70);
		sendingFacility.setNamespaceId(strNamespaceId);
		sendingFacility.setUniversalId(strUniversalId);
		sendingFacility.setUniversalIdType(strUniversalIdType); 
		setSendingFacility(sendingFacility);

	} 

	/** Set the Sending Facility.
	 * This field used as the HL7 identifier for the user-defined table of values for the first component.
	 * @param objsendingFacility object of Sending Facility. 
	 */ 
	public void setSendingFacility(HD objsendingFacility)
	{
		setDataType(70,objsendingFacility);

	}
	/** 
	 * Set the file Comment.
	 * This field contains the file Comment  for the file.
	 * @param strfileComment Specifies the file Comment.
	 * @return - function status [success/failure].
	 */ 
	public void setFileHeaderComment (String strfileComment) 
	{
		ST fileHeaderComment  = (ST)getDataElement(76);
		fileHeaderComment.setValue(strfileComment); 
		setFileHeaderComment(fileHeaderComment);
	} 

	/** Set the file Comment.
	 *  This field contains the file Comment  for the file.
	 *  @param objfileHeaderComment object of File header Comment.
	 */ 
	public void setFileHeaderComment(ST objfileHeaderComment)
	{
		setDataType(76,objfileHeaderComment);

	}
	/**
	 * Retrieves the File Comment.
	 * This field contains the File type
	 * @return ST - FileComment
	 */
	public ST getFileHeaderComment() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(76);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/** 
	 * Set the Reference File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @param strreferenceFileControlID Specifies a number or other identifier that uniquely identifies the File. 
	 */ 
	public void setReferenceFileControlID (String strreferenceFileControlID) 
	{
		ST referenceFileControlID  = (ST)getDataElement(78);
		referenceFileControlID.setValue(strreferenceFileControlID); 
		setReferenceFileControlID(referenceFileControlID);

	} 

	/** Set the Reference File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @param objreferenceFileControlID object of Reference File Control ID. 
	 */ 
	public void setReferenceFileControlID(ST objreferenceFileControlID)
	{
		setDataType(78,objreferenceFileControlID);

	}
	/**
	 * Retrieves the Reference File Control ID.
	 * This field contains a number or other identifier that uniquely identifies the File. 
	 * @return ST - referenceFileControlID
	 */
	public ST getReferenceFileControlID() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(78);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}
	
	/**
	 * Retrieves the File Sending Network Address.
	 * Identifier of the network location the message was transmitted from.  
	 * @return HD - receivingApplication
	 */
	public HD getFileSendingNetworkAddress()
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(2269);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}
	
	/** 
	 * Set the File Sending Network Address.
	 * Identifier of the network location the message was transmitted from.  
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */
	public void setFileSendingNetworkAddress(String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD receivingApplication  = (HD)getDataElement(2269);
		receivingApplication.setNamespaceId(strNamespaceId);
		receivingApplication.setUniversalId(strUniversalId);
		receivingApplication.setUniversalIdType(strUniversalIdType);
		setFileSendingNetworkAddress(receivingApplication);
	}

	/**
	 * Set the File Sending Network Address.
	 * Identifier of the network location the message was transmitted from.  
	 * @param objReceivingApplication Object of Receiving Application.
	 */
	public void setFileSendingNetworkAddress(HD objReceivingApplication)
	{
		setDataType(2269,objReceivingApplication);
	}

	/**
	 * Retrieves the File Receiving Network Address.
	 * Identifier of the network location the message was transmitted to.  
	 * @return HD - receivingApplication
	 */
	public HD getFileReceivingNetworkAddress()
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(2270);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (HD)objDataCollection.elementAt(0);
		else
			return null;
	}
	
	/** 
	 * Set the File Receiving Network Address.
	 * Identifier of the network location the message was transmitted to.  
	 * @param strNamespaceId Specifies Specifies  the HL7 identifier for the user-defined table of values for this component.[Refer Table No.300]
	 * @param strUniversalId Specifies a string formatted according to the scheme defined by the component, <universal ID type> (UID type). 
	 * @param strUniversalIdType Governs the interpretation of the strUniversalId. 
	 */
	public void setFileReceivingNetworkAddress(String strNamespaceId,String strUniversalId,String strUniversalIdType) 
	{
		HD receivingApplication  = (HD)getDataElement(2270);
		receivingApplication.setNamespaceId(strNamespaceId);
		receivingApplication.setUniversalId(strUniversalId);
		receivingApplication.setUniversalIdType(strUniversalIdType);
		setFileReceivingNetworkAddress(receivingApplication);
	}

	/**
	 * Set the File Receiving Network Address.
	 * Identifier of the network location the message was transmitted to.  
	 * @param objReceivingApplication Object of Receiving Application.
	 */
	public void setFileReceivingNetworkAddress(HD objReceivingApplication)
	{
		setDataType(2270,objReceivingApplication);
	}

	/**
	 * Validates HL7 Message objects .
	 * Validate method checks for validation each and every segments in side the Message object against specified message Structure. 
	 * Validation chcecks include optionality of segment or group.
	 * It also verifies the number of times segment or group is repeated in message.
	 * e.g 
	 * {PSH} while parsing PSH segment validate method will check for its mandatory presence.
	 * [PSH] in this case validate will throw exception if one tries to enter more than one PSH segment. 
	 * @return boolean - true or false.
	 * @throws InvalidSegmentException Thrown when Any of required filed is missing.
	 */
	public boolean validate() throws InvalidSegmentException
	{
		try
		{
			super.validate();
			return true;
		}
		catch(FieldMissingException ex)
		{
			throw new InvalidSegmentException(enumSegments.getValue(),ex);
		}
	}

	/**
	 * Serializes HL7 Message objects.
	 * Before serializaton it validates Message as per HL7 v2.5 standard.
	 * For successfull serialization , Message Object should follow order of segments as per its corresponding Message Structure. 
	 * Serialize method fails if given stream is null.
	 * It mandates presence of required segments and the number of occurences specified by the standard.
	 * This method also checks for presence of Mandatory Groups.It also verifies repeatability of Group.
	 * @param objIHL7Stream Object of IHL7Stream.
	 * @param objIDelimiter Object of class Delimiter.
	 * @return int - [failure or success].
	 * @throws SerializeException Thrown when serialization of Message fails. 
	 * @throws IOException  Signals that an I/O exception of some sort has occurred.
	 */
	public int serialize(IHL7Stream objIHL7Stream,IDelimiter objIDelimiter) throws SerializeException,IOException
	{
		try
		{
			ISingleCollection<Integer> objItemIDList = objSegmentMap.getItemIDList();
			// get the Character used as the repetition Seperator for the repeating field. 
			char cRSeparator = objIDelimiter.getRepetitionSeparator();
			if(cRSeparator == '\0')
				throw new DelimiterMissingException(ResourceBundleWrapper.getValue("exceptions", "RepetitionSeparatorMissing", new Locale(HL7Config.createInstance().getLocale())));			//get the Character used as the Field Seperator for Seperating the field. 
			char cFSeparator = objIDelimiter.getFieldSeparator();
			if(cFSeparator == '\0')
				throw new DelimiterMissingException(ResourceBundleWrapper.getValue("exceptions", "FieldSeparatorMissing", new Locale(HL7Config.createInstance().getLocale())));
			//write name of Segment.
			objIHL7Stream.writeString(EnumSegments.HL7_SEG_FHS.getValue());
			objIHL7Stream.writeChar(cFSeparator);
			//This write is called in plase of write on "encodingChar" field of FHS.
			objDelimiter.writeDelimiters(objIHL7Stream);
			objIHL7Stream.writeChar(cFSeparator);
			
			for(int seqno = 2; seqno < objItemIDList.size();seqno++)
			{
				int itemID = objItemIDList.elementAt(seqno);

				ISingleCollection<IDataType> objDataTypeList = objDataElementList.get(itemID);

				if(objDataTypeList != null)
				{
					int iSize = objDataTypeList.size();
					for(int index = 0; index < objDataTypeList.size(); index++)
					{
						IDataType objIDataType = objDataTypeList.elementAt(index);
						objIDataType.write(objIHL7Stream,objIDelimiter);

						if(index != iSize - 1)
							objIHL7Stream.writeChar(cRSeparator);
					}
				}
				if(seqno != objItemIDList.size() - 1)
				{
					//This Code checks next elements are present or not
					for(int i= seqno+1 ; i<objItemIDList.size();i++)
					{
						int itemID1 = objItemIDList.elementAt(i);
						ISingleCollection<IDataType> objDataTypeList1 = objDataElementList.get(itemID1);
						//If next element is present then it appends Field Separator
						if(objDataTypeList1 != null)
						{
							objIHL7Stream.writeChar(cFSeparator);
							break;
						}
					}
				}
			}

			//This character shows the end of the segment.
			objIHL7Stream.writeChar('\r');
			
			return HL7Constants.HL7_FUNCTION_SUCCESS;
		}
		catch(InvalidSegmentException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
		catch(DelimiterMissingException ex)
		{
			throw new SerializeException(this.getClass().getSimpleName(),ex);
		}
	}

	/**
	 * Parses HL7 Segment Strings from any Stream into HL7 Segment object.
	 * This method checks for the Repetition of the fields in the Segment.
	 * It also checks for the optionality of the fields as whether they are mandatory or optional.
	 * Successful parsing of the segment populates the object with the data present on the stream and provides
	 * easy accessor and mutator methods to navigate the message.
	 * It also leads to failure if version of given HL7 Message is not 2.8.2. 
	 * This method raises exception if there is Segment which is not valid as per HL7 v 2.8.2 standard.
	 * @param strSegmentStream String of HL7Stream.
	 * @param objIDelimiter Object of class Delimiter.
	 * @return int - Success if segment is valid.
	 * 			   - Fail if segment in not valid
	 * @throws InvalidSegmentException Thrown when Field Validation Fails.
	 * @throws IOException Signals that an I/O exception of some sort has occurred.
	 */	
	public int parse(String strSegmentStream,IDelimiter objIDelimiter) throws InvalidSegmentException,IOException
	{
		int iRetVal = HL7Constants.HL7_FUNCTION_FAIL;
		char cReadChar = '\0';
		try
		{
			int i= -1;
			do
			{
				String strField = "";
				String strTemp = "";
				//After FHS the next character is field separator.
				//Read Field Seperator
				cReadChar =strSegmentStream.charAt(++i);
				//Read value of field seperator to Delimiter
				objDelimiter.cFieldSeparator = cReadChar;
				strTemp = "" + cReadChar;
				ST fieldSeparator = (ST)getDataElement(67);
				fieldSeparator.setValue(strTemp);
				setDataType(67, fieldSeparator);
				//Read encoding char
				String encodingChars="";
				char ch=strSegmentStream.charAt(i);
				do
				{
					ch=strSegmentStream.charAt(++i);
					encodingChars=encodingChars+ch;
						
				}while(ch!='|' && ch!='\r');
				iRetVal = objDelimiter.readDelimiters(encodingChars);
				if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					setUnRecognizedField("FHS","File Encoding Characters",encodingChars);
					return iRetVal;
				}
				strTemp = "";
				strTemp = strTemp + objDelimiter.cComponentSeparator + objDelimiter.cRepetitionSeparator; 
				if(objDelimiter.cEscapeCharacter != '\0')
					strTemp = strTemp + objDelimiter.cEscapeCharacter + objDelimiter.cSubComponentSeparator;
				ST encodingChar = (ST)getDataElement(68);
				encodingChar.setValue(strTemp);
				setDataType(68, encodingChar);
				objIDelimiter = objDelimiter;
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;
				//Read Sending Application
				HD sendingApplication = (HD)getDataElement(69);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = sendingApplication.read(strField, objIDelimiter);
				if(iRetVal == 0)
					sendingApplication = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					sendingApplication = null;
					setUnRecognizedField("FHS","File Sending Application",encodingChars);
				}
				else
				{
					setDataType(69, sendingApplication);
					sendingApplication = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read Sending Facility
				HD sendingFacility = (HD)getDataElement(70);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = sendingFacility.read(strField, objIDelimiter);
				if(iRetVal == 0)
					sendingFacility = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					sendingFacility = null;
					setUnRecognizedField("FHS","File Sending Facility",encodingChars);
				}
				else
				{
					setDataType(70, sendingFacility);
					sendingFacility = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read Receiving Application
				HD receivingApplication = (HD)getDataElement(71);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = receivingApplication.read(strField, objIDelimiter);
				if(iRetVal == 0)
					receivingApplication = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					receivingApplication = null;
					setUnRecognizedField("FHS","File Receiving Application",encodingChars);
				}
				else
				{
					setDataType(71, receivingApplication);
					receivingApplication = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read Receiving Facility
				HD receivingFacility = (HD)getDataElement(72);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = receivingFacility.read(strField, objIDelimiter);
				if(iRetVal == 0)
					receivingFacility = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					receivingFacility = null;
					setUnRecognizedField("FHS","File Receiving Facility",encodingChars);
				}
				else
				{
					setDataType(72, receivingFacility);
					receivingFacility = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read Date-Time Of File
				DTM dateTimeOfFile = (DTM)getDataElement(73);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = dateTimeOfFile.read(strField, objIDelimiter);
				if(iRetVal == 0)
					dateTimeOfFile = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					dateTimeOfFile = null;
					setUnRecognizedField("FHS","File Creation Date/Time",encodingChars);
				}
				else
				{
					setDataType(73, dateTimeOfFile);
					dateTimeOfFile = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read Security
				ST security = (ST)getDataElement(74);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = security.read(strField, objIDelimiter);
				if(iRetVal == 0)
					security = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					security = null;
					setUnRecognizedField("FHS","File Security",encodingChars);
				}
				else
				{
					setDataType(74, security);
					security = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read File Type
				ST fileName = (ST)getDataElement(75);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = fileName.read(strField, objIDelimiter);
				if(iRetVal == 0)
					fileName = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					fileName = null;
					setUnRecognizedField("FHS","File Name/ID",encodingChars);
				}
				else
				{
					setDataType(75, fileName);
					fileName = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				// Read File Comment
				ST fileHeaderComment = (ST)getDataElement(76);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = fileHeaderComment.read(strField, objIDelimiter);
				if(iRetVal == 0)
					fileHeaderComment = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					fileHeaderComment = null;
					setUnRecognizedField("FHS","File Header Comment",encodingChars);
				}
				else
				{
					setDataType(76, fileHeaderComment);
					fileHeaderComment = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//Read File Control ID
				ST fileControlID = (ST)getDataElement(77);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = fileControlID.read(strField, objIDelimiter);
				if(iRetVal == 0)
					fileControlID = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					fileControlID = null;
					setUnRecognizedField("FHS","File Control ID",encodingChars);
				}
				else
				{
					setDataType(77, fileControlID);
					fileControlID = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				// Read Reference File Control ID
				ST referenceFileControlID = (ST)getDataElement(78);
				do
				{
					strField=strField+strSegmentStream.charAt(++i);
				
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = referenceFileControlID.read(strField, objIDelimiter);
				if(iRetVal == 0)
					referenceFileControlID = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					referenceFileControlID = null;
					setUnRecognizedField("FHS","Reference File Control ID",encodingChars);
				}
				else
				{
					setDataType(78, referenceFileControlID);
					referenceFileControlID = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;

				//File Sending Network Address
				HD fileSendingNetworkAddress = (HD)getDataElement(2272);
				do
				{
					strField = strField + strSegmentStream.charAt(++i);
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = fileSendingNetworkAddress.read(strField, objIDelimiter);
				if(iRetVal == 0)
					fileSendingNetworkAddress = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					fileSendingNetworkAddress = null;
					setUnRecognizedField("FHS","File Sending Network Address",encodingChars);
				}
				else
				{
					setDataType(2271 , fileSendingNetworkAddress);
					fileSendingNetworkAddress = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;
				
				//File Receiving Network Address
				HD fileReceivingNetworkAddress = (HD)getDataElement(2272);
				do
				{
					strField = strField + strSegmentStream.charAt(++i);
				}while(strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
				iRetVal = fileReceivingNetworkAddress.read(strField, objIDelimiter);
				if(iRetVal == 0)
					fileReceivingNetworkAddress = null;
				else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
				{
					fileReceivingNetworkAddress = null;
					setUnRecognizedField("FHS","File Receiving Network Address",encodingChars);
				}
				else
				{
					setDataType(2271 , fileReceivingNetworkAddress);
					fileReceivingNetworkAddress = null;
				}
				strField = "";
				cReadChar = '\0';
				cReadChar = strSegmentStream.charAt(i);
				if(cReadChar != objDelimiter.cFieldSeparator)
					break;
				
			}while((strSegmentStream.charAt(i) != '\0') &&  (strSegmentStream.charAt(i) != '\r'));	

			if((cReadChar == '\r'))
			{			
					return HL7Constants.HL7_FUNCTION_SUCCESS;

			}
			else
			{
				String strMessage = "Invalid segment teminator";
				throw new InvalidDelimiterException(strMessage);
			}
		}
		catch(InvalidDataTypeException ex)
		{
			throw new InvalidSegmentException(this.getClass().getSimpleName(), ex);
		}
		catch(FieldMissingException ex)
		{
			throw new InvalidSegmentException(this.getClass().getSimpleName(),ex);
		}
		catch(InvalidFieldException ex)
		{
			throw new InvalidSegmentException(this.getClass().getSimpleName(),ex);
		}
		catch(InvalidDelimiterException ex)
		{
			throw new InvalidSegmentException(this.getClass().getSimpleName(),ex);
		}
	}
}