/// <summary> /// Escape string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static String escape(String text, EncodingCharacters encChars) { //Note: Special character sequences are like \.br\. Items like this should not //be escaped using the \E\ method for the \'s. Instead, just tell the encoding to //skip these items. char[] textAsChar = text.ToCharArray(); StringBuilder result = new StringBuilder(text.Length); Hashtable specialCharacters = InvertHash(getEscapeSequences(encChars)); bool isEncodingSpecialCharacterSequence = false; bool encodeCharacter = false; for (int i = 0; i < textAsChar.Length; i++) { encodeCharacter = false; if (isEncodingSpecialCharacterSequence) { encodeCharacter = false; if (textAsChar[i].Equals(encChars.EscapeCharacter)) isEncodingSpecialCharacterSequence = false; } else { if (specialCharacters[textAsChar[i]] != null) { //Special character encodeCharacter = true; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { //Check for special escaping if (i < textAsChar.Length - 1) { //The data is specially escaped, treat it that way by not encoding the escape character if (_nonEscapeCharacterMapping[textAsChar[i].ToString() + textAsChar[i + 1].ToString()] != null) { //Start buffering this isEncodingSpecialCharacterSequence = true; encodeCharacter = false; } } } } } if (encodeCharacter) result.Append(specialCharacters[textAsChar[i]]); else result.Append(textAsChar[i]); } if (result.Length > 0) //return result.ToString().Trim(); return result.ToString(); else return ""; }
public static System.String Encode(ISegment source, EncodingCharacters encodingChars) { System.Text.StringBuilder result = new System.Text.StringBuilder(); result.Append(source.GetStructureName()); result.Append(encodingChars.FieldSeparator); //start at field 2 for MSH segment because field 1 is the field delimiter int startAt = 1; if (IsDelimDefSegment(source.GetStructureName())) { startAt = 2; } //loop through fields; for every field delimit any repetitions and add field delimiter after ... int numFields = source.NumFields(); for (int i = startAt; i <= numFields; i++) { try { IType[] reps = source.GetField(i); for (int j = 0; j < reps.Length; j++) { System.String fieldText = Encode(reps[j], encodingChars); //if this is MSH-2, then it shouldn't be escaped, so unescape it again if (IsDelimDefSegment(source.GetStructureName()) && i == 2) { fieldText = Escape.unescape(fieldText, encodingChars); } result.Append(fieldText); if (j < reps.Length - 1) { result.Append(encodingChars.RepetitionSeparator); } } } catch (HL7Exception e) { log.Error("Error while encoding segment: ", e); } result.Append(encodingChars.FieldSeparator); } //strip trailing delimiters ... return(StripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator)); }
public string encode() { NHapi.Base.Parser.EncodingCharacters ec = new NHapi.Base.Parser.EncodingCharacters(HL7Constants.FIELD_SEPARATOR, HL7Constants.DEFAULT_DELIMITER); StringBuilder sb = new StringBuilder(); sb.Append(PipeParser.Encode(this.MSH, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(QPD, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(getPid(), ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(RDF, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(RCP, ec)); return(sb.ToString()); }
/// <summary> Fills a field with values from an unparsed string representing the field. </summary> /// <param name="destinationField">the field Type /// </param> /// <param name="data">the field string (including all components and subcomponents; not including field delimiters) /// </param> /// <param name="encodingCharacters">the encoding characters used in the message /// </param> private static void Parse(IType destinationField, System.String data, EncodingCharacters encodingCharacters) { System.String[] components = Split(data, System.Convert.ToString(encodingCharacters.ComponentSeparator)); for (int i = 0; i < components.Length; i++) { System.String[] subcomponents = Split(components[i], System.Convert.ToString(encodingCharacters.SubcomponentSeparator)); for (int j = 0; j < subcomponents.Length; j++) { System.String val = subcomponents[j]; if (val != null) { val = Escape.unescape(val, encodingCharacters); } Terser.getPrimitive(destinationField, i + 1, j + 1).Value = val; } } }
public string encode() { NHapi.Base.Parser.EncodingCharacters ec = new NHapi.Base.Parser.EncodingCharacters(HL7Constants.FIELD_SEPARATOR, HL7Constants.DEFAULT_DELIMITER); StringBuilder sb = new StringBuilder(); sb.Append(PipeParser.Encode(this.MSH, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(QPD, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(getPid(), ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(RDF, ec)); sb.Append(HL7Constants.SEGMENT_SEPARATOR); sb.Append(PipeParser.Encode(RCP, ec)); return sb.ToString(); }
/// <summary> Encodes the given Type, using the given encoding characters. /// It is assumed that the Type represents a complete field rather than a component. /// </summary> public static System.String Encode(IType source, EncodingCharacters encodingChars) { System.Text.StringBuilder field = new System.Text.StringBuilder(); for (int i = 1; i <= Terser.numComponents(source); i++) { System.Text.StringBuilder comp = new System.Text.StringBuilder(); for (int j = 1; j <= Terser.numSubComponents(source, i); j++) { IPrimitive p = Terser.getPrimitive(source, i, j); comp.Append(EncodePrimitive(p, encodingChars)); comp.Append(encodingChars.SubcomponentSeparator); } field.Append(StripExtraDelimiters(comp.ToString(), encodingChars.SubcomponentSeparator)); field.Append(encodingChars.ComponentSeparator); } return(StripExtraDelimiters(field.ToString(), encodingChars.ComponentSeparator)); //return encode(source, encodingChars, false); }
/// <summary> /// Unescape the string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static String unescape(String text, EncodingCharacters encChars) { // is there an escape character in the text at all? if (text.IndexOf(encChars.EscapeCharacter) == -1) { return(text); } StringBuilder result = new StringBuilder(); int textLength = text.Length; Hashtable esc = getEscapeSequences(encChars); SupportClass.ISetSupport keys = new SupportClass.HashSetSupport(esc.Keys); String escChar = Convert.ToString(encChars.EscapeCharacter); int position = 0; while (position < textLength) { IEnumerator it = keys.GetEnumerator(); bool isReplaced = false; while (it.MoveNext() && !isReplaced) { String seq = (String)it.Current; String val = (String)esc[seq]; int seqLength = seq.Length; if (position + seqLength <= textLength) { if (text.Substring(position, (position + seqLength) - (position)).Equals(seq)) { result.Append(val); isReplaced = true; position = position + seq.Length; } } } if (!isReplaced) { result.Append(text.Substring(position, ((position + 1)) - (position))); position++; } } return(result.ToString()); }
/// <seealso cref="java.lang.Object.equals"> /// </seealso> public override bool Equals(System.Object o) { if (o is EncodingCharacters) { EncodingCharacters other = (EncodingCharacters)o; if (this.FieldSeparator == other.FieldSeparator && this.ComponentSeparator == other.ComponentSeparator && this.EscapeCharacter == other.EscapeCharacter && this.RepetitionSeparator == other.RepetitionSeparator && this.SubcomponentSeparator == other.SubcomponentSeparator) { return(true); } else { return(false); } } else { return(false); } }
/// <summary> Fills a field with values from an unparsed string representing the field. </summary> /// <param name="destinationField">the field Type. /// </param> /// <param name="data">the field string (including all components and subcomponents; not including field delimiters). /// </param> /// <param name="encodingCharacters">the encoding characters used in the message. /// </param> private static void Parse(IType destinationField, string data, EncodingCharacters encodingCharacters) { var components = Split(data, Convert.ToString(encodingCharacters.ComponentSeparator)); for (var i = 0; i < components.Length; i++) { var subcomponents = Split(components[i], Convert.ToString(encodingCharacters.SubcomponentSeparator)); for (var j = 0; j < subcomponents.Length; j++) { var val = subcomponents[j]; if (val != null) { val = Escape.UnescapeText(val, encodingCharacters); } Terser.GetPrimitive(destinationField, i + 1, j + 1).Value = val; } } }
/// <summary> /// Returns a HashTable with escape sequences as keys, and corresponding Strings as values. /// </summary> /// /// <param name="encChars"> . </param> /// /// <returns> The escape sequences. </returns> private static System.Collections.Hashtable getEscapeSequences(EncodingCharacters encChars) { //escape sequence strings must be assembled using the given escape character //see if this has already been done for this set of encoding characters System.Collections.Hashtable escapeSequences = null; System.Object o = variousEncChars[encChars]; if (o == null) { //this means we haven't got the sequences for these encoding characters yet - let's make them escapeSequences = makeEscapeSequences(encChars); variousEncChars[encChars] = escapeSequences; } else { //we already have escape sequences for these encoding characters escapeSequences = (System.Collections.Hashtable)o; } return(escapeSequences); }
/// <summary> /// Constructs escape sequences using the given escape character - this should only be called by /// getEscapeCharacter(), which will cache the results for subsequent use. /// </summary> /// /// <param name="ec"> The ec. </param> /// /// <returns> A list of. </returns> private static System.Collections.Hashtable makeEscapeSequences(EncodingCharacters ec) { System.Collections.Hashtable seqs = new System.Collections.Hashtable(); char[] codes = { 'F', 'S', 'T', 'R', 'E' }; char[] values = { ec.FieldSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator, ec.RepetitionSeparator, ec.EscapeCharacter }; for (int i = 0; i < codes.Length; i++) { System.Text.StringBuilder seq = new System.Text.StringBuilder(); seq.Append(ec.EscapeCharacter); seq.Append(codes[i]); seq.Append(ec.EscapeCharacter); seqs[seq.ToString()] = System.Convert.ToString(values[i]); } seqs["\\X000d\\"] = System.Convert.ToString('\r'); return(seqs); }
/// <summary> /// Encodes the given Type, using the given encoding characters. /// It is assumed that the Type represents a complete field rather than a component. /// </summary> public static string Encode(IType source, EncodingCharacters encodingChars) { var field = new StringBuilder(); for (var i = 1; i <= Terser.NumComponents(source); i++) { var comp = new StringBuilder(); for (var j = 1; j <= Terser.NumSubComponents(source, i); j++) { var p = Terser.GetPrimitive(source, i, j); comp.Append(EncodePrimitive(p, encodingChars)); comp.Append(encodingChars.SubcomponentSeparator); } field.Append(StripExtraDelimiters(comp.ToString(), encodingChars.SubcomponentSeparator)); field.Append(encodingChars.ComponentSeparator); } return(StripExtraDelimiters(field.ToString(), encodingChars.ComponentSeparator)); }
/// <summary> Constructs escape sequences using the given escape character - this should only /// be called by getEscapeCharacter(), which will cache the results for subsequent use. /// </summary> private static Hashtable makeEscapeSequences(EncodingCharacters ec) { Hashtable seqs = new Hashtable(); char[] codes = new char[] { 'F', 'S', 'T', 'R', 'E' }; char[] values = new char[] { ec.FieldSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator, ec.RepetitionSeparator, ec.EscapeCharacter }; for (int i = 0; i < codes.Length; i++) { StringBuilder seq = new StringBuilder(); seq.Append(ec.EscapeCharacter); seq.Append(codes[i]); seq.Append(ec.EscapeCharacter); seqs[seq.ToString()] = Convert.ToString(values[i]); } // \\x....\\ denotes hexadecimal escaping // Convert the .... hexadecimal values into decimal, which map to ascii characters seqs["\\X000d\\"] = Convert.ToString('\r'); // 00 > null, 0D > CR seqs["\\X0A\\"] = Convert.ToString('\n'); // 0A > LF return(seqs); }
/// <summary> Parses a message string and returns the corresponding Message /// object. Unexpected segments added at the end of their group. /// /// </summary> /// <throws> HL7Exception if the message is not correctly formatted. </throws> /// <throws> EncodingNotSupportedException if the message encoded </throws> /// <summary> is not supported by this parser. /// </summary> protected internal override IMessage DoParse(System.String message, System.String version) { //try to instantiate a message object of the right class MessageStructure structure = GetStructure(message); IMessage m = InstantiateMessage(structure.messageStructure, version, structure.explicitlyDefined); //MessagePointer ptr = new MessagePointer(this, m, getEncodingChars(message)); MessageIterator messageIter = new MessageIterator(m, "MSH", true); FilterIterator.IPredicate segmentsOnly = new AnonymousClassPredicate(this); FilterIterator segmentIter = new FilterIterator(messageIter, segmentsOnly); System.String[] segments = Split(message, segDelim); EncodingCharacters encodingChars = GetEncodingChars(message); for (int i = 0; i < segments.Length; i++) { //get rid of any leading whitespace characters ... if (segments[i] != null && segments[i].Length > 0 && System.Char.IsWhiteSpace(segments[i][0])) { segments[i] = StripLeadingWhitespace(segments[i]); } //sometimes people put extra segment delimiters at end of msg ... if (segments[i] != null && segments[i].Length >= 3) { System.String name = segments[i].Substring(0, (3) - (0)); log.Debug("Parsing segment " + name); messageIter.Direction = name; FilterIterator.IPredicate byDirection = new AnonymousClassPredicate1(name, this); FilterIterator dirIter = new FilterIterator(segmentIter, byDirection); if (dirIter.MoveNext()) { Parse((ISegment)dirIter.Current, segments[i], encodingChars); } } } return(m); }
/// <summary> /// Parses a segment string and populates the given Segment object. /// <para> /// Unexpected fields are added as Varies' at the end of the segment. /// </para> /// </summary> /// <param name="destination">Segment to parse the segment string into.</param> /// <param name="segment">Encoded segment.</param> /// <param name="encodingChars">Encoding characters to be used.</param> /// <param name="repetition">The repetition number of this segment within its group.</param> /// <exception cref="HL7Exception"> /// If the given string does not contain the given segment or if the string is not encoded properly. /// </exception> public virtual void Parse(ISegment destination, string segment, EncodingCharacters encodingChars, int repetition) { Parse(destination, segment, encodingChars, repetition, DefaultParserOptions); }
/// <summary> /// Parses a segment string and populates the given Segment object. /// <para> /// Unexpected fields are added as Varies' at the end of the segment. /// </para> /// </summary> /// <param name="destination">Segment to parse the segment string into.</param> /// <param name="segment">Encoded segment.</param> /// <param name="encodingChars">Encoding characters to be used.</param> /// <param name="repetition">The repetition number of this segment within its group.</param> /// <param name="parserOptions">Contains configuration that will be applied when parsing.</param> /// <exception cref="HL7Exception"> /// If the given string does not contain the given segment or if the string is not encoded properly. /// </exception> public virtual void Parse(ISegment destination, string segment, EncodingCharacters encodingChars, int repetition, ParserOptions parserOptions) { parserOptions = parserOptions ?? DefaultParserOptions; var fieldOffset = 0; if (IsDelimDefSegment(destination.GetStructureName())) { fieldOffset = 1; // set field 1 to fourth character of string Terser.Set(destination, 1, 0, 1, 1, Convert.ToString(encodingChars.FieldSeparator)); } var fields = Split(segment, Convert.ToString(encodingChars.FieldSeparator)); for (var i = 1; i < fields.Length; i++) { var reps = Split(fields[i], Convert.ToString(encodingChars.RepetitionSeparator)); if (Log.DebugEnabled) { Log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator); } // MSH-2 will get split incorrectly so we have to fudge it ... var isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2; if (isMSH2) { reps = new string[1]; reps[0] = fields[i]; } for (var j = 0; j < reps.Length; j++) { try { var statusMessage = $"Parsing field {i + fieldOffset} repetition {j}"; Log.Debug(statusMessage); var field = destination.GetField(i + fieldOffset, j); if (isMSH2) { Terser.GetPrimitive(field, 1, 1).Value = reps[j]; } else { Parse(field, reps[j], encodingChars); } } catch (HL7Exception e) { // set the field location and throw again ... e.FieldPosition = i; if (repetition > 1) { e.SegmentRepetition = repetition; } e.SegmentName = destination.GetStructureName(); throw; } } } // set data type of OBX-5 if (destination.GetType().FullName.IndexOf("OBX") >= 0) { Varies.FixOBX5(destination, Factory, parserOptions); } }
/// <summary> /// Escape string. /// </summary> /// <param name="text"></param> /// <param name="encodingCharacters"></param> /// <returns></returns> public static string EscapeText(string text, EncodingCharacters encodingCharacters) { var lookup = BuildEncodingLookups(encodingCharacters); var result = new StringBuilder(); for (var i = 0; i < text.Length; i++) { var charReplaced = false; var currentCharacter = text[i]; if (!lookup.SpecialCharacters.Contains(currentCharacter)) { result.Append(currentCharacter); continue; } // Formatting escape sequences such as \.br\ should be left alone if (currentCharacter == encodingCharacters.EscapeCharacter) { var nextCharacterIndex = i + 1; if (nextCharacterIndex < text.Length) { var nextCharacter = text[nextCharacterIndex]; // Check for \.br\ switch (nextCharacter) { case '.': case 'C': case 'M': case 'X': case 'Z': var nextEscapeCharacterIndex = text.IndexOf(currentCharacter, nextCharacterIndex); if (nextEscapeCharacterIndex > 0) { result.Append(text, i, (nextEscapeCharacterIndex + 1) - i); charReplaced = true; i = nextEscapeCharacterIndex; } break; case 'H': case 'N': var twoCharactersAheadIndex = i + 2; if (twoCharactersAheadIndex < text.Length && text[twoCharactersAheadIndex] == encodingCharacters.EscapeCharacter) { if (twoCharactersAheadIndex > 0) { result.Append(text, i, (twoCharactersAheadIndex + 1) - i); charReplaced = true; i = twoCharactersAheadIndex; } } break; } } } if (charReplaced) { continue; } result.Append(lookup.EscapeSequences[currentCharacter]); } return(result.ToString()); }
/// <summary> /// Parses a segment string and populates the given Segment object. /// <para> /// Unexpected fields are added as Varies' at the end of the segment. /// </para> /// </summary> /// <param name="destination">Segment to parse the segment string into.</param> /// <param name="segment">Encoded segment.</param> /// <param name="encodingChars">Encoding characters to be used.</param> /// <param name="parserOptions">Contains configuration that will be applied when parsing.</param> /// <exception cref="HL7Exception"> /// If the given string does not contain the given segment or if the string is not encoded properly. /// </exception> public virtual void Parse(ISegment destination, string segment, EncodingCharacters encodingChars, ParserOptions parserOptions) { parserOptions = parserOptions ?? DefaultParserOptions; Parse(destination, segment, encodingChars, 0, parserOptions); }
/// <summary> Parses a segment string and populates the given Segment object. Unexpected fields are /// added as Varies' at the end of the segment. /// /// </summary> /// <throws> HL7Exception if the given string does not contain the </throws> /// <summary> given segment or if the string is not encoded properly /// </summary> public virtual void Parse(ISegment destination, String segment, EncodingCharacters encodingChars) { int fieldOffset = 0; if (IsDelimDefSegment(destination.GetStructureName())) { fieldOffset = 1; //set field 1 to fourth character of string Terser.Set(destination, 1, 0, 1, 1, Convert.ToString(encodingChars.FieldSeparator)); } String[] fields = Split(segment, Convert.ToString(encodingChars.FieldSeparator)); for (int i = 1; i < fields.Length; i++) { String[] reps = Split(fields[i], Convert.ToString(encodingChars.RepetitionSeparator)); if (log.DebugEnabled) { log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator); } //MSH-2 will get split incorrectly so we have to fudge it ... bool isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2; if (isMSH2) { reps = new String[1]; reps[0] = fields[i]; } for (int j = 0; j < reps.Length; j++) { try { StringBuilder statusMessage = new StringBuilder("Parsing field "); statusMessage.Append(i + fieldOffset); statusMessage.Append(" repetition "); statusMessage.Append(j); log.Debug(statusMessage.ToString()); IType field = destination.GetField(i + fieldOffset, j); if (isMSH2) { Terser.getPrimitive(field, 1, 1).Value = reps[j]; } else { Parse(field, reps[j], encodingChars); } } catch (HL7Exception e) { //set the field location and throw again ... e.FieldPosition = i + fieldOffset; e.SegmentRepetition = MessageIterator.getIndex(destination.ParentStructure, destination).rep; e.SegmentName = destination.GetStructureName(); throw; } } } //set data type of OBX-5 if (destination.GetType().FullName.IndexOf("OBX") >= 0) { Varies.fixOBX5(destination, Factory); } }
public static string escape(string text, EncodingCharacters encChars) { return(EscapeText(text, encChars)); }
/// <summary> Fills a field with values from an unparsed string representing the field. </summary> /// <param name="destinationField">the field Type /// </param> /// <param name="data">the field string (including all components and subcomponents; not including field delimiters) /// </param> /// <param name="encodingCharacters">the encoding characters used in the message /// </param> private static void Parse(IType destinationField, String data, EncodingCharacters encodingCharacters) { String[] components = Split(data, Convert.ToString(encodingCharacters.ComponentSeparator)); for (int i = 0; i < components.Length; i++) { String[] subcomponents = Split(components[i], Convert.ToString(encodingCharacters.SubcomponentSeparator)); for (int j = 0; j < subcomponents.Length; j++) { String val = subcomponents[j]; if (val != null) { val = Escape.unescape(val, encodingCharacters); } Terser.getPrimitive(destinationField, i + 1, j + 1).Value = val; } } }
private static String EncodePrimitive(IPrimitive p, EncodingCharacters encodingChars) { String val = ((IPrimitive) p).Value; if (val == null) { val = ""; } else { val = Escape.escape(val, encodingChars); } return val; }
/// <summary> Parses a segment string and populates the given Segment object. Unexpected fields are /// added as Varies' at the end of the segment. /// /// </summary> /// <throws> HL7Exception if the given string does not contain the </throws> /// <summary> given segment or if the string is not encoded properly /// </summary> public virtual void Parse(ISegment destination, System.String segment, EncodingCharacters encodingChars) { int fieldOffset = 0; if (IsDelimDefSegment(destination.GetStructureName())) { fieldOffset = 1; //set field 1 to fourth character of string Terser.Set(destination, 1, 0, 1, 1, System.Convert.ToString(encodingChars.FieldSeparator)); } System.String[] fields = Split(segment, System.Convert.ToString(encodingChars.FieldSeparator)); //destination.setName(fields[0]); for (int i = 1; i < fields.Length; i++) { System.String[] reps = Split(fields[i], System.Convert.ToString(encodingChars.RepetitionSeparator)); if (log.DebugEnabled) { log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator); } //MSH-2 will get split incorrectly so we have to fudge it ... bool isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2; if (isMSH2) { reps = new System.String[1]; reps[0] = fields[i]; } for (int j = 0; j < reps.Length; j++) { try { System.Text.StringBuilder statusMessage = new System.Text.StringBuilder("Parsing field "); statusMessage.Append(i + fieldOffset); statusMessage.Append(" repetition "); statusMessage.Append(j); log.Debug(statusMessage.ToString()); //parse(destination.GetField(i + fieldOffset, j), reps[j], encodingChars, false); IType field = destination.GetField(i + fieldOffset, j); if (isMSH2) { Terser.getPrimitive(field, 1, 1).Value = reps[j]; } else { Parse(field, reps[j], encodingChars); } } catch (HL7Exception e) { //set the field location and throw again ... e.FieldPosition = i; e.SegmentRepetition = MessageIterator.getIndex(destination.ParentStructure, destination).rep; e.SegmentName = destination.GetStructureName(); throw e; } } } //set data type of OBX-5 if (destination.GetType().FullName.IndexOf("OBX") >= 0) { Varies.fixOBX5(destination, Factory); } }
/// <summary>Returns the component or subcomponent separator from the given encoding characters. </summary> private static char GetSeparator(bool subComponents, EncodingCharacters encodingChars) { char separator; if (subComponents) { separator = encodingChars.SubcomponentSeparator; } else { separator = encodingChars.ComponentSeparator; } return separator; }
public static String Encode(ISegment source, EncodingCharacters encodingChars) { StringBuilder result = new StringBuilder(); result.Append(source.GetStructureName()); result.Append(encodingChars.FieldSeparator); //start at field 2 for MSH segment because field 1 is the field delimiter int startAt = 1; if (IsDelimDefSegment(source.GetStructureName())) startAt = 2; //loop through fields; for every field delimit any repetitions and add field delimiter after ... int numFields = source.NumFields(); for (int i = startAt; i <= numFields; i++) { try { IType[] reps = source.GetField(i); for (int j = 0; j < reps.Length; j++) { String fieldText = Encode(reps[j], encodingChars); //if this is MSH-2, then it shouldn't be escaped, so unescape it again if (IsDelimDefSegment(source.GetStructureName()) && i == 2) fieldText = Escape.unescape(fieldText, encodingChars); result.Append(fieldText); if (j < reps.Length - 1) result.Append(encodingChars.RepetitionSeparator); } } catch (HL7Exception e) { log.Error("Error while encoding segment: ", e); } result.Append(encodingChars.FieldSeparator); } //strip trailing delimiters ... return StripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator); }
/// <summary> Returns given group serialized as a pipe-encoded string - this method is called /// by encode(Message source, String encoding). /// </summary> public static String Encode(IGroup source, EncodingCharacters encodingChars) { StringBuilder result = new StringBuilder(); String[] names = source.Names; for (int i = 0; i < names.Length; i++) { IStructure[] reps = source.GetAll(names[i]); for (int rep = 0; rep < reps.Length; rep++) { if (reps[rep] is IGroup) { result.Append(Encode((IGroup) reps[rep], encodingChars)); } else { String segString = Encode((ISegment) reps[rep], encodingChars); if (segString.Length >= 4) { result.Append(segString); result.Append('\r'); } } } } return result.ToString(); }
/// <summary> Formats a Message object into an HL7 message string using this parser's /// default encoding ("VB"). /// </summary> /// <throws> HL7Exception if the data fields in the message do not permit encoding </throws> /// <summary> (e.g. required fields are null) /// </summary> protected internal override String DoEncode(IMessage source) { //get encoding characters ... ISegment msh = (ISegment) source.GetStructure("MSH"); String fieldSepString = Terser.Get(msh, 1, 0, 1, 1); if (fieldSepString == null) { //cdc: This was breaking when trying to construct a blank message, and there is no way to set the fieldSeperator, so fill in a default //throw new HL7Exception("Can't encode message: MSH-1 (field separator) is missing"); fieldSepString = "|"; Terser.Set(msh, 1, 0, 1, 1, fieldSepString); } char fieldSep = '|'; if (fieldSepString != null && fieldSepString.Length > 0) fieldSep = fieldSepString[0]; String encCharString = Terser.Get(msh, 2, 0, 1, 1); if (encCharString == null) { //cdc: This was breaking when trying to construct a blank message, and there is no way to set the EncChars, so fill in a default //throw new HL7Exception("Can't encode message: MSH-2 (encoding characters) is missing"); encCharString = @"^~\&"; Terser.Set(msh, 2, 0, 1, 1, encCharString); } string version = Terser.Get(msh, 12, 0, 1, 1); if (version == null) { //Put in the message version Terser.Set(msh, 12, 0, 1, 1, source.Version); } string msgStructure = Terser.Get(msh, 9, 0, 1, 1); if (msgStructure == null) { //Create the MsgType and Trigger Event if not there string messageTypeFullname = source.GetStructureName(); int i = messageTypeFullname.IndexOf("_"); if (i > 0) { string type = messageTypeFullname.Substring(0, i); string triggerEvent = messageTypeFullname.Substring(i + 1); Terser.Set(msh, 9, 0, 1, 1, type); Terser.Set(msh, 9, 0, 2, 1, triggerEvent); } else { Terser.Set(msh, 9, 0, 1, 1, messageTypeFullname); } } if (encCharString.Length != 4) throw new HL7Exception("Encoding characters '" + encCharString + "' invalid -- must be 4 characters", HL7Exception.DATA_TYPE_ERROR); EncodingCharacters en = new EncodingCharacters(fieldSep, encCharString); //pass down to group encoding method which will operate recursively on children ... return Encode((IGroup) source, en); }
/// <summary> /// Parses a segment string and populates the given Segment object. /// <para> /// Unexpected fields are added as Varies' at the end of the segment. /// </para> /// </summary> /// <param name="destination">Segment to parse the segment string into.</param> /// <param name="segment">Encoded segment.</param> /// <param name="encodingChars">Encoding characters to be used.</param> /// <exception cref="HL7Exception"> /// If the given string does not contain the given segment or if the string is not encoded properly. /// </exception> public virtual void Parse(ISegment destination, string segment, EncodingCharacters encodingChars) { Parse(destination, segment, encodingChars, 0); }
/// <summary> /// Unescape the string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static System.String unescape(System.String text, EncodingCharacters encChars) { System.Text.StringBuilder result = new System.Text.StringBuilder(); int textLength = text.Length; System.Collections.Hashtable esc = getEscapeSequences(encChars); SupportClass.ISetSupport keys = new SupportClass.HashSetSupport(esc.Keys); System.String escChar = System.Convert.ToString(encChars.EscapeCharacter); int position = 0; while (position < textLength) { System.Collections.IEnumerator it = keys.GetEnumerator(); bool isReplaced = false; while (it.MoveNext() && !isReplaced) { System.String seq = (System.String)it.Current; System.String val = (System.String)esc[seq]; int seqLength = seq.Length; if (position + seqLength <= textLength) { if (text.Substring(position, (position + seqLength) - (position)).Equals(seq)) { result.Append(val); isReplaced = true; position = position + seq.Length; } } } if (!isReplaced) { result.Append(text.Substring(position, ((position + 1)) - (position))); position++; } } return result.ToString(); }
/// <summary> Constructs escape sequences using the given escape character - this should only /// be called by getEscapeCharacter(), which will cache the results for subsequent use. /// </summary> private static System.Collections.Hashtable makeEscapeSequences(EncodingCharacters ec) { System.Collections.Hashtable seqs = new System.Collections.Hashtable(); char[] codes = new char[] { 'F', 'S', 'T', 'R', 'E' }; char[] values = new char[] { ec.FieldSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator, ec.RepetitionSeparator, ec.EscapeCharacter }; for (int i = 0; i < codes.Length; i++) { System.Text.StringBuilder seq = new System.Text.StringBuilder(); seq.Append(ec.EscapeCharacter); seq.Append(codes[i]); seq.Append(ec.EscapeCharacter); seqs[seq.ToString()] = System.Convert.ToString(values[i]); } seqs["\\X000d\\"] = System.Convert.ToString('\r'); return seqs; }
/// <summary> Encodes the given Type, using the given encoding characters. /// It is assumed that the Type represents a complete field rather than a component. /// </summary> public static String Encode(IType source, EncodingCharacters encodingChars) { StringBuilder field = new StringBuilder(); for (int i = 1; i <= Terser.numComponents(source); i++) { StringBuilder comp = new StringBuilder(); for (int j = 1; j <= Terser.numSubComponents(source, i); j++) { IPrimitive p = Terser.getPrimitive(source, i, j); comp.Append(EncodePrimitive(p, encodingChars)); comp.Append(encodingChars.SubcomponentSeparator); } field.Append(StripExtraDelimiters(comp.ToString(), encodingChars.SubcomponentSeparator)); field.Append(encodingChars.ComponentSeparator); } return StripExtraDelimiters(field.ToString(), encodingChars.ComponentSeparator); //return encode(source, encodingChars, false); }
/// <summary> /// Escape string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static String escape(String text, EncodingCharacters encChars) { //Note: Special character sequences are like \.br\. Items like this should not //be escaped using the \E\ method for the \'s. Instead, just tell the encoding to //skip these items. char[] textAsChar = text.ToCharArray(); StringBuilder result = new StringBuilder(text.Length); Hashtable specialCharacters = InvertHash(getEscapeSequences(encChars)); bool isEncodingSpecialCharacterSequence = false; bool encodeCharacter = false; for (int i = 0; i < textAsChar.Length; i++) { encodeCharacter = false; if (isEncodingSpecialCharacterSequence) { encodeCharacter = false; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { isEncodingSpecialCharacterSequence = false; } } else { if (specialCharacters[textAsChar[i]] != null) { //Special character encodeCharacter = true; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { //Check for special escaping if (i < textAsChar.Length - 1) { //The data is specially escaped, treat it that way by not encoding the escape character if (_nonEscapeCharacterMapping[textAsChar[i].ToString() + textAsChar[i + 1].ToString()] != null) { //Start buffering this isEncodingSpecialCharacterSequence = true; encodeCharacter = false; } } } } } if (encodeCharacter) { result.Append(specialCharacters[textAsChar[i]]); } else { result.Append(textAsChar[i]); } } if (result.Length > 0) { return(result.ToString().Trim()); } else { return(""); } }
/// <summary> /// Escape string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static String escape(String text, EncodingCharacters encChars) { //Note: Special character sequences are like \.br\. Items like this should not //be escaped using the \E\ method for the \'s. Instead, just tell the encoding to //skip these items. char[] textAsChar = text.ToCharArray(); StringBuilder result = new StringBuilder(text.Length); Hashtable specialCharacters = InvertHash(getEscapeSequences(encChars)); bool isEncodingSpecialCharacterSequence = false; bool encodeCharacter = false; for (int i = 0; i < textAsChar.Length; i++) { encodeCharacter = false; if (isEncodingSpecialCharacterSequence) { encodeCharacter = false; if (textAsChar[i].Equals(encChars.EscapeCharacter)) isEncodingSpecialCharacterSequence = false; } else { if (specialCharacters[textAsChar[i]] != null) { //Special character encodeCharacter = true; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { int nextEscapeChar = text.IndexOf(encChars.EscapeCharacter, i + 1); if (nextEscapeChar == i + 2) { //The data is specially escaped, treat it that way by not encoding the escape character if (_singleCharNonEscapeCharacterMapping[textAsChar[i + 1].ToString()] != null) { //Start buffering this encodeCharacter = false; isEncodingSpecialCharacterSequence = true; } } else if (nextEscapeChar != -1) { if (_multiCharNonEscapeCharacterMapping[textAsChar[i + 1].ToString()] != null) { // Contains /#xxyyzz..nn/ from the main string. string potentialEscapeSequence = text.Substring(i, nextEscapeChar - i + 1); bool encodeCharacter1 = true; // Get the hex component by striping initial slash, escape character, and last slash. Need to substring at index 2 for length - 3 characters. string hex = potentialEscapeSequence.Substring(2, potentialEscapeSequence.Length - 3); if (hex.Length % 2 == 0) { switch (potentialEscapeSequence.Substring(0, 2)) { case "\\C": // Look for closing character of \Cxxyy\ if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\M": // Look for closing character of \Mxxyy\ or Mxxyyzz if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\X": if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\Z": // We don't support this. //if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) //{ // encodeCharacter = false; // isEncodingSpecialCharacterSequence = true; //} break; } } encodeCharacter = encodeCharacter1; } } } } } if (encodeCharacter) result.Append(specialCharacters[textAsChar[i]]); else result.Append(textAsChar[i]); } if (result.Length > 0) return result.ToString().Trim(); else return ""; }
/// <summary> Formats a Message object into an HL7 message string using this parser's /// default encoding ("VB"). /// </summary> /// <throws> HL7Exception if the data fields in the message do not permit encoding </throws> /// <summary> (e.g. required fields are null) /// </summary> protected internal override System.String DoEncode(IMessage source) { //get encoding characters ... ISegment msh = (ISegment)source.GetStructure("MSH"); System.String fieldSepString = Terser.Get(msh, 1, 0, 1, 1); if (fieldSepString == null) { //cdc: This was breaking when trying to construct a blank message, and there is no way to set the fieldSeperator, so fill in a default //throw new HL7Exception("Can't encode message: MSH-1 (field separator) is missing"); fieldSepString = "|"; Terser.Set(msh, 1, 0, 1, 1, fieldSepString); } char fieldSep = '|'; if (fieldSepString != null && fieldSepString.Length > 0) { fieldSep = fieldSepString[0]; } System.String encCharString = Terser.Get(msh, 2, 0, 1, 1); if (encCharString == null) { //cdc: This was breaking when trying to construct a blank message, and there is no way to set the EncChars, so fill in a default //throw new HL7Exception("Can't encode message: MSH-2 (encoding characters) is missing"); encCharString = @"^~\&"; Terser.Set(msh, 2, 0, 1, 1, encCharString); } string version = Terser.Get(msh, 12, 0, 1, 1); if (version == null) { //Put in the message version Terser.Set(msh, 12, 0, 1, 1, source.Version); } string msgStructure = Terser.Get(msh, 9, 0, 1, 1); if (msgStructure == null) { //Create the MsgType and Trigger Event if not there string messageTypeFullname = source.GetStructureName(); int i = messageTypeFullname.IndexOf("_"); if (i > 0) { string type = messageTypeFullname.Substring(0, i); string triggerEvent = messageTypeFullname.Substring(i + 1); Terser.Set(msh, 9, 0, 1, 1, type); Terser.Set(msh, 9, 0, 2, 1, triggerEvent); } else { Terser.Set(msh, 9, 0, 1, 1, messageTypeFullname); } } if (encCharString.Length != 4) { throw new HL7Exception("Encoding characters '" + encCharString + "' invalid -- must be 4 characters", HL7Exception.DATA_TYPE_ERROR); } EncodingCharacters en = new EncodingCharacters(fieldSep, encCharString); //pass down to group encoding method which will operate recursively on children ... return(Encode((IGroup)source, en)); }
/// <summary> /// Un-escape the string. /// </summary> /// <param name="text"></param> /// <param name="encodingCharacters"></param> /// <returns></returns> public static string UnescapeText(string text, EncodingCharacters encodingCharacters) { // If the escape char isn't found, we don't need to look for escape sequences // is there an escape character in the text at all? if (text.IndexOf(encodingCharacters.EscapeCharacter) == -1) { return(text); } var result = new StringBuilder(); var lookup = BuildEncodingLookups(encodingCharacters); for (var i = 0; i < text.Length; i++) { var currentCharacter = text[i]; if (currentCharacter != encodingCharacters.EscapeCharacter) { result.Append(currentCharacter); continue; } var foundEncoding = false; foreach (var keyValuePair in lookup.EscapeSequences) { var escapeSequence = keyValuePair.Value; var character = keyValuePair.Key; var escapeSequenceLength = escapeSequence.Length; var canExtractSubstring = i + escapeSequenceLength <= text.Length; if (canExtractSubstring && text.Substring(i, escapeSequenceLength).Equals(escapeSequence)) { result.Append(character); i += escapeSequenceLength - 1; foundEncoding = true; break; } } if (foundEncoding) { continue; } // If we haven't found this, there is one more option. Escape sequences of /.XXXXX/ are // formatting codes. They should be left intact var nextCharacterIndex = i + 1; if (nextCharacterIndex < text.Length) { var nextCharacter = text[nextCharacterIndex]; var closingEscapeIndex = text.IndexOf(encodingCharacters.EscapeCharacter, nextCharacterIndex); var escapeSequenceLength = (closingEscapeIndex + 1) - i; switch (nextCharacter) { case '.': case 'C': case 'M': case 'X': case 'Z': if (closingEscapeIndex > 0) { var substring = text.Substring(i, escapeSequenceLength); result.Append(substring); i += substring.Length - 1; } break; case 'H': case 'N': var twoCharactersAheadIndex = i + 2; if (closingEscapeIndex == twoCharactersAheadIndex) { var substring = text.Substring(i, escapeSequenceLength); result.Append(substring); i += substring.Length - 1; } break; } } } return(result.ToString()); }
public static void Main(System.String[] args) { System.String testString = "foo$r$this is $ $p$test$r$r$ string"; //System.out.println(testString); //System.out.println(replace(testString, "$r$", "***")); //System.out.println(replace(testString, "$", "+")); //test speed gain with cache int n = 100000; System.Collections.Hashtable seqs; EncodingCharacters ec = new EncodingCharacters('|', "^~\\&"); //warm up the JIT for (int i = 0; i < n; i++) { seqs = makeEscapeSequences(ec); } for (int i = 0; i < n; i++) { seqs = getEscapeSequences(ec); } //time long start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; for (int i = 0; i < n; i++) { seqs = makeEscapeSequences(ec); } System.Console.Out.WriteLine("Time to make " + n + " times: " + ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start)); start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; for (int i = 0; i < n; i++) { seqs = getEscapeSequences(ec); } System.Console.Out.WriteLine("Time to get " + n + " times: " + ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start)); start = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; for (int i = 0; i < n; i++) { seqs = makeEscapeSequences(ec); } System.Console.Out.WriteLine("Time to make " + n + " times: " + ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start)); //test escape: testString = "this | is ^ a field \\T\\ with & some ~ bad stuff \\T\\"; System.Console.Out.WriteLine("Original: " + testString); System.String escaped = escape(testString, ec); System.Console.Out.WriteLine("Escaped: " + escaped); System.Console.Out.WriteLine("Unescaped: " + unescape(escaped, ec)); }
public EncodingLookups(EncodingCharacters encoding) { LoadHexadecimalConfiguration(); BuildLookups(encoding); }
/// <summary> Returns a HashTable with escape sequences as keys, and corresponding /// Strings as values. /// </summary> private static System.Collections.Hashtable getEscapeSequences(EncodingCharacters encChars) { //escape sequence strings must be assembled using the given escape character //see if this has already been done for this set of encoding characters System.Collections.Hashtable escapeSequences = null; System.Object o = variousEncChars[encChars]; if (o == null) { //this means we haven't got the sequences for these encoding characters yet - let's make them escapeSequences = makeEscapeSequences(encChars); variousEncChars[encChars] = escapeSequences; } else { //we already have escape sequences for these encoding characters escapeSequences = (System.Collections.Hashtable)o; } return escapeSequences; }
/// <summary> Constructs escape sequences using the given escape character - this should only /// be called by getEscapeCharacter(), which will cache the results for subsequent use. /// </summary> private static Hashtable makeEscapeSequences(EncodingCharacters ec) { Hashtable seqs = new Hashtable(); char[] codes = new char[] {'F', 'S', 'T', 'R', 'E'}; char[] values = new char[] {ec.FieldSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator, ec.RepetitionSeparator, ec.EscapeCharacter}; for (int i = 0; i < codes.Length; i++) { StringBuilder seq = new StringBuilder(); seq.Append(ec.EscapeCharacter); seq.Append(codes[i]); seq.Append(ec.EscapeCharacter); seqs[seq.ToString()] = Convert.ToString(values[i]); } // \\x....\\ denotes hexadecimal escaping // Convert the .... hexadecimal values into decimal, which map to ascii characters seqs["\\X000d\\"] = Convert.ToString('\r'); // 00 > null, 0D > CR seqs["\\X0A\\"] = Convert.ToString('\n'); // 0A > LF return seqs; }
/// <summary>copies contents of "other" </summary> public EncodingCharacters(EncodingCharacters other) { this.fieldSep = other.FieldSeparator; this.encChars = new char[4]; this.encChars[0] = other.ComponentSeparator; this.encChars[1] = other.RepetitionSeparator; this.encChars[2] = other.EscapeCharacter; this.encChars[3] = other.SubcomponentSeparator; }
/// <summary> /// Escape string /// </summary> /// <param name="text"></param> /// <param name="encChars"></param> /// <returns></returns> public static String escape(String text, EncodingCharacters encChars) { //Note: Special character sequences are like \.br\. Items like this should not //be escaped using the \E\ method for the \'s. Instead, just tell the encoding to //skip these items. char[] textAsChar = text.ToCharArray(); StringBuilder result = new StringBuilder(text.Length); Hashtable specialCharacters = InvertHash(getEscapeSequences(encChars)); bool isEncodingSpecialCharacterSequence = false; bool encodeCharacter = false; for (int i = 0; i < textAsChar.Length; i++) { encodeCharacter = false; if (isEncodingSpecialCharacterSequence) { encodeCharacter = false; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { isEncodingSpecialCharacterSequence = false; } } else { if (specialCharacters[textAsChar[i]] != null) { //Special character encodeCharacter = true; if (textAsChar[i].Equals(encChars.EscapeCharacter)) { int nextEscapeChar = text.IndexOf(encChars.EscapeCharacter, i + 1); if (nextEscapeChar == i + 2) { //The data is specially escaped, treat it that way by not encoding the escape character if (_singleCharNonEscapeCharacterMapping[textAsChar[i + 1].ToString()] != null) { //Start buffering this encodeCharacter = false; isEncodingSpecialCharacterSequence = true; } } else if (nextEscapeChar != -1) { if (_multiCharNonEscapeCharacterMapping[textAsChar[i + 1].ToString()] != null) { // Contains /#xxyyzz..nn/ from the main string. string potentialEscapeSequence = text.Substring(i, nextEscapeChar - i + 1); bool encodeCharacter1 = true; // Get the hex component by striping initial slash, escape character, and last slash. Need to substring at index 2 for length - 3 characters. string hex = potentialEscapeSequence.Substring(2, potentialEscapeSequence.Length - 3); if (hex.Length % 2 == 0) { switch (potentialEscapeSequence.Substring(0, 2)) { case "\\C": // Look for closing character of \Cxxyy\ if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\M": // Look for closing character of \Mxxyy\ or Mxxyyzz if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\X": if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) { encodeCharacter1 = false; isEncodingSpecialCharacterSequence = true; } break; case "\\Z": // We don't support this. //if (hex.All(c => HexDigits.Contains(char.ToUpper(c)))) //{ // encodeCharacter = false; // isEncodingSpecialCharacterSequence = true; //} break; } } encodeCharacter = encodeCharacter1; } } } } } if (encodeCharacter) { result.Append(specialCharacters[textAsChar[i]]); } else { result.Append(textAsChar[i]); } } if (result.Length > 0) { return(result.ToString().Trim()); } else { return(""); } }