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

import cdac.medinfo.sdk.hl7282.baselibs.CWE;
import cdac.medinfo.sdk.hl7282.baselibs.DTM;
import cdac.medinfo.sdk.hl7282.baselibs.FN;
import cdac.medinfo.sdk.hl7282.baselibs.HD;
import cdac.medinfo.sdk.hl7282.baselibs.ID;
import cdac.medinfo.sdk.hl7282.baselibs.ST;
import cdac.medinfo.sdk.hl7282.baselibs.XCN;
import cdac.medinfo.sdk.hl7282.baselibs.segmentfactory.DataElementFactory;
import cdac.medinfo.sdk.hl7282.commoninterface.IDataType;
import cdac.medinfo.sdk.hl7282.commoninterface.IDelimiter;
import cdac.medinfo.sdk.hl7282.commoninterface.ISingleCollection;
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.hl7streams.HL7BufferStream;
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;
import cdac.medinfo.sdk.hl7282.utils.SingleCollection;

/**
 * MFE - Master File Entry Segment. <p>
 * The Technical Steward for the MFE segment is CQ.
 * <p>Represents an HL7 MFE message segment. 
 * This segment has the following fields:</p><p>
 * MFE-1: Record-Level Event Code (ID)<b>Required</b><br> 
 * MFE-2: MFN Control ID (ST)<b>Conditional</b><br> 
 * MFE-3: Effective Date/Time (DTM)<b>Optional</b><br> 
 * MFE-4: Primary Key Value - MFE (Varies)<b>Required</b><br> 
 * MFE-5: Primary Key Value Type (ID)<b>Required</b><br>
 * MFE-6: Entered Date/Time (DTM)<b>Optional</b><br> 
 * MFE-7: Entered By (XCN)<b>Optional</b><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 MFE extends Segment   
{
	

	/***
	 * Constructs the MFE segment.
	 */
	public MFE()
	{
		super(EnumSegments.HL7_SEG_MFE);
	}

	/**
	 * Retrieves the Effective Date Time.
	 * This date/time the originating system expects that the event is to have been completed on the receiving system.  
	 * @return DTM - effectiveDateTime
	 */
	public DTM getEffectiveDateTime() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(662);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (DTM)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the MFN Control ID.
	 * This field uniquely identify this change to this record from the point of view of the originating system.
	 * @return ST - mFNControlID
	 */
	public ST getMFNControlID() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(665);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ST)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Retrieves the Primary Key Value MFE.
	 * This field uniquely identify the record of the master file.
	 * @return ISingleCollection<IDataType> - primaryKeyValueMFE
	 */
	public ISingleCollection<IDataType> getPrimaryKeyValueMFE() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(667);
		ISingleCollection<IDataType> objDataList = new SingleCollection<IDataType>(); 
		if(objDataCollection != null && objDataCollection.size() != 0)
		{
			for(IDataType objDataType : objDataCollection)
			{
				objDataList.add(objDataType);
			}
		}
		return objDataList;
	}

	/**
	 * Retrieves the Primary Key Value Type.
	 * @return ISingleCollection<ID> - primaryKeyValueType
	 */
	public ISingleCollection<ID> getPrimaryKeyValueType() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(1319);
		ISingleCollection<ID> objDataList = new SingleCollection<ID>(); 
		if(objDataCollection != null && objDataCollection.size() != 0)
		{
			for(IDataType objDataType : objDataCollection)
			{
				ID objID = (ID)objDataType;
				objDataList.add(objID);
			}
		}
		return objDataList;
	}

	/**
	 * Retrieves the Record Level Event Code.
	 * This field defines the record-level event for the master file 
	 * record identified by the MFI segment and the primary key field in this segment.   
	 * @return ID - recordLevelEventCode
	 */
	public ID getRecordLevelEventCode() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(664);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (ID)objDataCollection.elementAt(0);
		else
			return null;
	}
	
	/**
	 * Retrieves the Entered Date/Time.
	 * This field contains the date and time of the last change of the record.
	 * @return DTM - EnteredDateTime
	 */
	public DTM getEnteredDateTime() 
	{
		ISingleCollection<IDataType> objDataCollection =getDataType(661);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (DTM)objDataCollection.elementAt(0);
		else
			return null;
	}
	
	/**
	 * Retrieves the Entered By.
	 * This field contains the identity of the person who actually keyed the master file entry into the application.
	 * @return XCN - EnteredBy
	 */
	public XCN getEnteredBy() 
	{
		ISingleCollection<IDataType> objDataCollection = getDataType(224);
		if(objDataCollection != null && objDataCollection.size() != 0) 
			return (XCN)objDataCollection.elementAt(0);
		else
			return null;
	}

	/**
	 * Add the Primary Key Value MFE.
	 * This field uniquely identify the record of the master file.
	 * @param objPrimaryKeyValueMFE Used as PrimaryKeyValueMFE.
	 */
	public void addprimaryKeyValueMFE(IDataType objPrimaryKeyValueMFE)
	{
		addDataType(667,objPrimaryKeyValueMFE);
	}

	/**
	 * Set the Primary Key Value MFE.
	 * This field uniquely identify the record of the master file.
	 * @param objPrimaryKeyValueMFEList List Used as PrimaryKeyValueMFE.
	 */
	@SuppressWarnings("unchecked")
	public void setprimaryKeyValueMFE(ISingleCollection<IDataType> objPrimaryKeyValueMFEList)
	{
		ISingleCollection<IDataType> objCollection = null;
		ISingleCollection<?> objUnknownCollection = (ISingleCollection<?>)objPrimaryKeyValueMFEList;
		objCollection = (ISingleCollection<IDataType>)objUnknownCollection;
		setDataType(667,objCollection);
	}

	/**
	 * Set the Effective Date Time.
	 * This date/time the originating system expects that the event is to have been completed on the receiving system.  
	 * @param strTime Specifies a point in time using a 24-hour clock notation. 
	 * @param strDegreeOfPrecision The degree of precision of the time stamp .Suggested Values Y,L,D,H,M,S [Refer to HL7 Table 0529].
	 */ 
	public void setEffectiveDateTime (String strTime) 
	{
		DTM effectiveDateTime  = (DTM)getDataElement(662);
		effectiveDateTime.setValue(strTime);
		setEffectiveDateTime(effectiveDateTime);

	} 

	/**Sets the Effective Date Time  
	 * @param objeffectiveDateTime object of Effective Date Time
	 */ 
	public void setEffectiveDateTime(DTM objeffectiveDateTime)
	{
		setDataType(662,objeffectiveDateTime);

	}
	/**
	 * Set the MFN Control ID.
	 * This field uniquely identify this change to this record from the point of view of the originating system.
	 * @param strAccidentDecription Used as AccidentDecription.
	 */ 
	public void setMFNControlID (String strAccidentDecription) 
	{
		ST mFNControlID  = (ST)getDataElement(665);
		mFNControlID.setValue(strAccidentDecription); 
		setMFNControlID(mFNControlID);
	} 

	/** Set the MFN Control ID.
	 * This field uniquely identify this change to this record from the point of view of the originating system.
	 * @param objmFNControlID object of MFN Control ID.
	 */ 
	public void setMFNControlID(ST objmFNControlID)
	{
		setDataType(665,objmFNControlID);
	}
	/**
	 * Add the Primary Key Value Type.
	 * @param strCharacterSet USed as CharacterSet.
	 */ 
	public void addPrimaryKeyValueType (String strCharacterSet) 
	{
		ID tempPrimaryKeyValueType  = (ID)getDataElement(1319);
		tempPrimaryKeyValueType.setValue(strCharacterSet); 
		addPrimaryKeyValueType(tempPrimaryKeyValueType);
	} 

	/** Add the Primary Key Value Type.
	 * @param objtempPrimaryKeyValueType object of Primary Key Value Type.
	 */ 
	public void addPrimaryKeyValueType(ID objtempPrimaryKeyValueType)
	{
		addDataType(1319,objtempPrimaryKeyValueType);
	}	 

	/** Set the Primary Key Value Type.
	 * @param objtempPrimaryKeyValueTypeList List of Primary Key Value Type.
	 */ 
	@SuppressWarnings("unchecked")
	public void setPrimaryKeyValueType(ISingleCollection<ID> objtempPrimaryKeyValueTypeList)
	{
		ISingleCollection<IDataType> objCollection = null;
		ISingleCollection<?> objUnknownCollection = (ISingleCollection<?>)objtempPrimaryKeyValueTypeList;
		objCollection = (ISingleCollection<IDataType>)objUnknownCollection;
		setDataType(1319,objCollection);
	}

	/**
	 * Set the Record Level Event Code.
	 * This field defines the record-level event for the master file 
	 * record identified by the MFI segment and the primary key field in this segment.
	 * @param strQueryResponseStatus Used as QueryResponseStatus.
	 */ 
	public void setRecordLevelEventCode (String strQueryResponseStatus) 
	{
		ID recordLevelEventCode  = (ID)getDataElement(664);
		recordLevelEventCode.setValue(strQueryResponseStatus); 
		setRecordLevelEventCode(recordLevelEventCode);

	} 

	/** Set the Record Level Event Code.
	 * This field defines the record-level event for the master file 
	 * record identified by the MFI segment and the primary key field in this segment.
	 * @param objrecordLevelEventCode object of Record Level Event Code.
	 */ 
	public void setRecordLevelEventCode(ID objrecordLevelEventCode)
	{
		setDataType(664,objrecordLevelEventCode);

	}
	
	/**
	 * Set the Entered By.
	 * This field contains the identity of the person who actually keyed the master file entry into the application. 
	 * @param strIDNumber Refers to the coded ID according to a user-defined table
	 * @param objFamilyName Specifies the surname of a person.
	 * @param strGivenName Specifies First name.
	 * @param strSecondAndFurtherGivenNamesOrInitialsThereof Specifies multiple middle names that may be included by 
	 * 														   separating them with spaces.
	 * @param strSuffix Used to specify a name suffix (e.g., Jr. or III).
	 * @param strPrefix Used to specify a name prefix (e.g., Dr.).
	 * @param strSourceTable Used as the HL7 identifier for the user-defined table of values for this component. [Refer User-defined Table 0297 - CN ID.]
	 * @param objAssigningAuthority Specifies a unique identifier of the system (or organization or agency of department)
	 * 								  that creates the data. [Refer User-defined Table 0363 - Assigning authority]
	 * @param strNameTypeCode Specifies a code that represents the type of name. 
	 * @param strIdentifierCheckDigit Specifies part of the identifying number used in the sending application. 
	 * @param strCheckDigitScheme Specifies the code identifying the check digit scheme employed.[Refer HL7 Table 0061 - Check digit scheme].
	 * @param strIdentifierTypeCode Specifies A code corresponding to the type of identifier.[Refer HL7 Table 0203 - Identifier type].
	 * @param objAssigningFacility Specifies the place or location identifier where the identifier was first assigned to the person
	 * @param strNameRepresentationCode Provides an indication of the representation provided by the data item.  
	 * @param objNameContext Designates the context in which a name is used. [Refer User-defined Table 0448 ]
	 * @param strNameAssemblyOrder Specifies a code that represents the preferred display order of the components of this person name. Suggested values are G,F[Refer table 0444.]
	 * @param strEffectiveDate Specifies the first date, if known, on which the address is valid and active.
	 * @param strExpirationDate Specifies the last date, if known, on which the address is valid and active.
	 * @param strProfessionalSuffix Used to specify an abbreviation, or a string of abbreviations, denoting qualifications that support the person's profession, (e.g., licenses).
	 * @param objAssigningJurisdiction Specifies the geo-political body that assigned the identifier.
	 * @param objAssigningAgencyOrDepratment Specifies the agency or department that assigned the identifier
	 * @param strSecurityCheck Specifies the version code that may be assigned to the person identifier
	 * @param strSecurityCheckScheme Specifies the check digit scheme.
	 */ 
	public void setEnteredBy (String strIDNumber,FN objFamilyName,String strGivenName,String strSecondAndFurtherGivenNamesOrInitialsThereof,
			String 	strSuffix,String strPrefix,CWE objSourceTable,HD objAssigningAuthority,
			String strNameTypeCode,String strIdentifierCheckDigit,String strCheckDigitScheme,String strIdentifierTypeCode,
			HD objAssigningFacility,String strNameRepresentationCode,CWE objNameContext,
			String strNameAssemblyOrder, String strEffectiveDate,String strExpirationDate,String strProfessionalSuffix,
			CWE objAssigningJurisdiction,CWE objAssigningAgencyOrDepratment, String strSecurityCheck, String strSecurityCheckScheme)
	{
		XCN xcn  = (XCN)getDataElement(224);
		xcn.setIdNumber(strIDNumber);
		xcn.setFamilyName(objFamilyName);
		xcn.setGivenName(strGivenName);
		xcn.setSecondNameOrInitials(strSecondAndFurtherGivenNamesOrInitialsThereof);
		xcn.setSuffix(strSuffix);
		xcn.setPrefix(strPrefix);
 
		xcn.setSourceTable(objSourceTable);
		xcn.setAssigningAuthority(objAssigningAuthority);
		xcn.setNameTypeCode(strNameTypeCode);
		xcn.setIdentifierCheckDigit(strIdentifierCheckDigit);
		xcn.setCheckDigitScheme(strCheckDigitScheme);
		xcn.setIdentifierTypeCode(strIdentifierTypeCode);
		xcn.setAssigningFacility(objAssigningFacility);
		xcn.setNameRepresentationCode(strNameRepresentationCode);
		xcn.setNameContext(objNameContext);
 
		xcn.setNameAssemblyOrder(strNameAssemblyOrder);
		xcn.setEffectiveDate(strEffectiveDate);
		xcn.setExpirationDate(strExpirationDate);
		xcn.setProfessionalSuffix(strProfessionalSuffix);
		xcn.setAssigningJurisdiction(objAssigningJurisdiction);
		xcn.setAssigningAgencyOrDepartment(objAssigningAgencyOrDepratment); 
		xcn.setSecurityCheck(strSecurityCheck);
		xcn.setSecurityCheckScheme(strSecurityCheckScheme);
		setEnteredBy(xcn);

	} 

	/**
	 * Set the Entered By. 
	 * This field contains the identity of the person who actually keyed the master file entry into the application.
	 * @param objEnteredBy
	 */ 
	public void setEnteredBy(XCN objEnteredBy)
	{
		setDataType(224,objEnteredBy);

	}


	/**
	 * 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 strHL7segmentString Object 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 Segment 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;
				DataElementFactory objDataElementFactory = DataElementFactory.createInstance();
				char cReadChar = '\0';
				int i = -1;
				IDataType objIDataType = null;
				try
				{
					//get field separator from IDelimiter
					char cFSeparator = objIDelimiter.getFieldSeparator();
					cReadChar = strSegmentStream.charAt(++i);

					if(cReadChar == cFSeparator)
					{
						String strEnumSegment = enumSegments.getValue();
						if(strEnumSegment.length() > 3)
						{
							strEnumSegment = strEnumSegment.substring(0, 3);
						}
						ISingleCollection<Integer> objItemIDList = objSegmentMap.getItemIDList();
						int[] iValueTable = null;
						String strDTName = null;
						int iMinLength = 0;
						int iMaxLength = 0;
						String strCLength = null;
						boolean isOptional;
						String strFieldName = null;
						for(Integer objItemID : objItemIDList)
						{
							strDTName = objSegmentMap.getDataTypeName(objItemID);
							iValueTable = objSegmentMap.getValueTable(objItemID);
							iMinLength = objSegmentMap.getItemMinimumLength(objItemID);
							iMaxLength = objSegmentMap.getItemMaximumLength(objItemID);
							strCLength = objSegmentMap.getItemConformanceLength(objItemID);
							strFieldName = objSegmentMap.getFieldName(objItemID);
							isOptional=objSegmentMap.isOptional(objItemID);
							do
							{
								String strField="";
								objIDataType = objDataElementFactory.getDataElement(iValueTable,iMinLength, iMaxLength,strCLength, strDTName,HL7Constants.HL7_COMPONENT);
								if(objIDataType == null)
								{
									// if Data Type is withdrawn then skip that value by reading stream till next delimiter
									cReadChar = strSegmentStream.charAt(++i);
									strField=""+cReadChar;
									while(cReadChar != cFSeparator && cReadChar != '\r')
									{
										cReadChar=strSegmentStream.charAt(++i);
										strField= strField+cReadChar;
									}
									if(strField!=null && strField.charAt(0) != '|')
										setUnRecognizedField(strEnumSegment, strFieldName, strField);
								}
								else
								{
									do
									{
										i++;
										strField=strField+strSegmentStream.charAt(i);
									}while(strSegmentStream.charAt(i) != '~' && strSegmentStream.charAt(i)!='|' && strSegmentStream.charAt(i)!='\r');
									iRetVal = objIDataType.read(strField, objIDelimiter);
			
									if(iRetVal == 0)
									{
										if(!isOptional)
										{
											setUnRecognizedField(strEnumSegment, strFieldName, strField);
										}
										objIDataType = null;
										cReadChar = '\0';
										cReadChar = strSegmentStream.charAt(i);
										break;
									}
									else if(iRetVal == HL7Constants.HL7_FUNCTION_FAIL)
									{
										objIDataType = null;
										setUnRecognizedField(strEnumSegment, strFieldName, strField);
									}
									else if(iRetVal == -1)  
									{
										//Avoids the reading of extra characters from stream when Components data type is withdrawn
										objIDataType = null;
										cReadChar = '\0';
										cReadChar= objIDelimiter.getFieldSeparator();
										break;
									}
									else if(iRetVal == HL7Constants.HL7_WITHDRAWN_FIELD)
									{
										setUnRecognizedField(strEnumSegment, strFieldName, strField);
									}
									else
									{
										objDataElementList.put(objItemID,objIDataType);
										objIDataType = null;
									}
									cReadChar = '\0';
									cReadChar = strSegmentStream.charAt(i);
								}
							}while(cReadChar == objIDelimiter.getRepetitionSeparator());

							if(cReadChar != cFSeparator)
								break;
						}
					}


					if(cReadChar == '\r')
					{
						/*
						 * Conversion code for PrimaryKeyValue-MFE according to the value specified in PrimaryKeyValueType
						 * In initial parsing this field has been  parsed as UN.
						 */
						ISingleCollection<ID> objTypeList = getPrimaryKeyValueType();
						ISingleCollection<IDataType> objValueList = getPrimaryKeyValueMFE();
						if(objTypeList != null && objValueList != null && objTypeList.size() == objValueList.size())
						{
							int index = 0;
							ISingleCollection<IDataType> objPrimaryKeyValueList = new SingleCollection<IDataType>();
							int iSize = objTypeList.size();
							while(index < iSize)
							{
								ID objID = objTypeList.elementAt(index);
								String strDatatype = (String)objID.getValue();

								IDataType objTargetDataType = DataElementFactory.createInstance().getDataElement(9999,0 ,200, "200#" ,strDatatype,HL7Constants.HL7_COMPONENT);
								if(objTargetDataType != null)
								{
									//Serializing UN value to stream
									IDataType objUN = objValueList.elementAt(index);
									ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
									HL7BufferStream objHL7BufferStream = new HL7BufferStream();
									objHL7BufferStream.setOutputStream(objByteArrayOutputStream);
									objUN.write(objHL7BufferStream,objIDelimiter);

									//converting value to specified Data type
									ByteArrayInputStream objByteArrayInputStream = new ByteArrayInputStream(objByteArrayOutputStream.toByteArray());
									objHL7BufferStream.setInputStream(objByteArrayInputStream);
									String strTemp = "";
									if(objHL7BufferStream!= null)
									{
										
										char readCh;
										do
										{
											readCh = objHL7BufferStream.readChar();
											strTemp=strTemp+readCh;
										}while(readCh != '\0');
									}
									objTargetDataType.read(strTemp,objIDelimiter);
									objPrimaryKeyValueList.add(objTargetDataType);
								}
								index++;
							}
							if(objPrimaryKeyValueList.size() == iSize)
							{
								/*
								 * If all occurrences has been modified only then attribute will be replaced.
								 */
								setDataType(667,objPrimaryKeyValueList);
							}
						}

						return HL7Constants.HL7_FUNCTION_SUCCESS;	
					}
					else
						return HL7Constants.HL7_INVALID_SEGMENT_TERMINATOR;

				}
				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);
				}
			}
	
	/**
	 * Set the Entered Date/Time.
	 * This field contains the date and time of the last change of the record.
	 * @param strTime The point in time
	 */ 
	public void setEnteredDateTime (String strTime) 
	{
		DTM EnteredDateTime  = (DTM)getDataElement(661);
		EnteredDateTime.setValue(strTime);
		setEnteredDateTime (EnteredDateTime);

	} 

	/** Set the Entered Date/Time.
	 * This field contains the date and time of the last change of the record.
	 * @param objEnteredDateTime
	 */ 
	public void setEnteredDateTime(DTM objEnteredDateTime)
	{
		setDataType(661,objEnteredDateTime);

	}

	/**
	 * 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 Throws when Segment Validation fails 
	 */	
	@Override
	public boolean validate() throws InvalidSegmentException 
	{
		try 
		{
			super.validate();

			//validation for Primary Key Value - MFA and Primary Key Value Type - MFA
			ISingleCollection<ID> objTypeList = getPrimaryKeyValueType();
			ISingleCollection<IDataType> objValueList = getPrimaryKeyValueMFE();
			if(objTypeList.size() != objValueList.size())
			{
				String str = ResourceBundleWrapper.getValue("exceptions", "InvalidField", new Locale(HL7Config.createInstance().getLocale())) + ":" + objSegmentMap.getFieldName(667) + ":" + objSegmentMap.getFieldName(1319);
				
					throw new InvalidFieldException(str);
			}

			return true;
		}
		catch(FieldMissingException ex)
		{
			throw new InvalidSegmentException(enumSegments.getValue(),ex);
		}
	}
}