Skip to content

Commit 1899713

Browse files
committed
Add support for multiple UnexpectedSegmentBehaviour options
1 parent 9dfbcc6 commit 1899713

File tree

9 files changed

+210
-55
lines changed

9 files changed

+210
-55
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88
## [3.1.0] - TBC
99

1010
### Enhancements
11+
- [#254](https://github.com/nHapiNET/nHapi/pull/254) Add `UnexpectedSegmentBehaviour` Options, ported from hapi
1112
- [#251](https://github.com/nHapiNET/nHapi/pull/251) Fix concurrency issues with `PipeParser`, `StructureDefinition`, `GenericMessage` and `Escape`.
1213
- [#250](https://github.com/nHapiNET/nHapi/pull/250) Add new options `DefaultObx2Type` and `InvalidObx2Type` to `ParserOptions`, ported from nhapi. (fixes [#63](https://github.com/nHapiNET/nHapi/issues/63))
1314
- [#240](https://github.com/nHapiNET/nHapi/pull/240) Add support for `NonGreedyMode` by introducing `ParserOptions` ported from hapi. (fixes [#65](https://github.com/nHapiNET/nHapi/issues/65) [#232](https://github.com/nHapiNET/nHapi/issues/232))

src/NHapi.Base/Parser/LegacyPipeParser.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,12 @@ public virtual void Parse(ISegment destination, string segment, EncodingCharacte
477477
/// <summary> <p>Returns a minimal amount of data from a message string, including only the
478478
/// data needed to send a response to the remote system. This includes the
479479
/// following fields:
480-
/// <ul><li>field separator</li>
481-
/// <li>encoding characters</li>
482-
/// <li>processing ID</li>
483-
/// <li>message control ID</li></ul>
480+
/// <list type="bullet">
481+
/// <item><description>field separator</description></item>
482+
/// <item><description>encoding characters</description></item>
483+
/// <item><description>processing ID</description></item>
484+
/// <item><description>message control ID</description></item>
485+
/// </list>
484486
/// This method is intended for use when there is an error parsing a message,
485487
/// (so the Message object is unavailable) but an error message must be sent
486488
/// back to the remote system including some of the information in the inbound

src/NHapi.Base/Parser/MessageIterator.cs

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -55,28 +55,33 @@ public MessageIterator(
5555
this.parserOptions = parserOptions;
5656
}
5757

58-
/// <summary> <p>Returns the next node in the message. Sometimes the next node is
58+
/// <summary>
59+
/// <para>
60+
/// Returns the next node in the message. Sometimes the next node is
5961
/// ambiguous. For example at the end of a repeating group, the next node
6062
/// may be the first segment in the next repetition of the group, or the
6163
/// next sibling, or an undeclared segment locally added to the group's end.
62-
/// Cases like this are disambiguated using getDirection(), which returns
64+
/// Cases like this are disambiguated using <see cref="Direction"/>, which returns
6365
/// the name of the structure that we are "iterating towards".
6466
/// Usually we are "iterating towards" a segment of a certain name because we
6567
/// have a segment string that we would like to parse into that node.
66-
/// Here are the rules: </p>
67-
/// <ol><li>If at a group, next means first child.</li>
68-
/// <li>If at a non-repeating segment, next means next "position"</li>
69-
/// <li>If at a repeating segment: if segment name matches
70-
/// direction then next means next rep, otherwise next means next "position".</li>
71-
/// <li>If at a segment within a group (not at the end of the group), next "position"
72-
/// means next sibling</li>
73-
/// <li>If at the end of a group: If name of group or any of its "first
68+
/// Here are the rules:
69+
/// </para>
70+
/// <list type="bullet">
71+
/// <item><description>If at a group, next means first child.</description></item>
72+
/// <item><description>If at a non-repeating segment, next means next "position"</description></item>
73+
/// <item><description>If at a repeating segment: if segment name matches
74+
/// direction then next means next rep, otherwise next means next "position".</description></item>
75+
/// <item><description>If at a segment within a group (not at the end of the group), next "position"
76+
/// means next sibling</description></item>
77+
/// <item><description>If at the end of a group: If name of group or any of its "first
7478
/// descendants" matches direction, then next position means next rep of group. Otherwise
7579
/// if direction matches name of next sibling of the group, or any of its first
7680
/// descendants, next position means next sibling of the group. Otherwise, next means a
77-
/// new segment added to the group (with a name that matches "direction"). </li>
78-
/// <li>"First descendants" means first child, or first child of the first child,
79-
/// or first child of the first child of the first child, etc. </li> </ol>
81+
/// new segment added to the group (with a name that matches "direction").</description></item>
82+
/// <item><description>"First descendants" means first child, or first child of the first child,
83+
/// or first child of the first child of the first child, etc.</description></item>
84+
/// </list>
8085
/// </summary>
8186
public virtual object Current
8287
{
@@ -233,26 +238,25 @@ private void AddNonStandardSegmentAtCurrentPosition()
233238
Log.Debug(
234239
$"Creating non standard segment {direction} on group: {GetCurrentPosition().StructureDefinition.Parent.Name}");
235240

236-
// TODO: make configurable like hapi?
237-
// switch (message.getParser().getParserConfiguration().getUnexpectedSegmentBehaviour())
238-
// {
239-
// case ADD_INLINE:
240-
// default:
241-
// parentDefinitionPath = new ArrayList<>(myCurrentDefinitionPath.subList(0, myCurrentDefinitionPath.size() - 1));
242-
// parentStructure = (IGroup)navigateToStructure(parentDefinitionPath);
243-
// break;
244-
// case DROP_TO_ROOT:
245-
// parentDefinitionPath = new ArrayList<>(myCurrentDefinitionPath.subList(0, 1));
246-
// parentStructure = myMessage;
247-
// myCurrentDefinitionPath = myCurrentDefinitionPath.subList(0, 2);
248-
// break;
249-
// case THROW_HL7_EXCEPTION:
250-
// throw new Error(new HL7Exception("Found unknown segment: " + myDirection));
251-
// }
252-
253-
// default hapi behaviour
254-
var parentDefinitionPath = new List<Position>(currentDefinitionPath.GetRange(0, currentDefinitionPath.Count - 1));
255-
var parentStructure = (IGroup)NavigateToStructure(parentDefinitionPath);
241+
List<Position> parentDefinitionPath;
242+
IGroup parentStructure;
243+
244+
switch (parserOptions.UnexpectedSegmentBehaviour)
245+
{
246+
case UnexpectedSegmentBehaviour.AddInline:
247+
parentDefinitionPath = new List<Position>(currentDefinitionPath.GetRange(0, currentDefinitionPath.Count - 1));
248+
parentStructure = (IGroup)NavigateToStructure(parentDefinitionPath);
249+
break;
250+
case UnexpectedSegmentBehaviour.DropToRoot:
251+
parentDefinitionPath = new List<Position>(currentDefinitionPath.GetRange(0, 1));
252+
parentStructure = this.message;
253+
currentDefinitionPath = currentDefinitionPath.GetRange(0, 2);
254+
break;
255+
case UnexpectedSegmentBehaviour.ThrowHl7Exception:
256+
throw new HL7Exception($"Found unknown segment: {direction}");
257+
default:
258+
throw new HL7Exception($"UnexpectedSegmentBehaviour.{parserOptions.UnexpectedSegmentBehaviour} is not currently handled.");
259+
}
256260

257261
// Current position within parent
258262
var currentPosition = GetCurrentPosition();

src/NHapi.Base/Parser/ParserBase.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,10 @@ public bool SupportsEncoding(string encoding)
380380
/// data needed to send a response to the remote system.
381381
/// <para>This includes the following fields:</para>
382382
/// <list type="bullet">
383-
/// <listHeader>field separator</listHeader>
384-
/// <item>encoding characters</item>
385-
/// <item>processing ID</item>
386-
/// <item>message control ID</item>
383+
/// <item><description>field separator</description></item>
384+
/// <item><description>encoding characters</description></item>
385+
/// <item><description>processing ID</description></item>
386+
/// <item><description>message control ID</description></item>
387387
/// </list>
388388
/// This method is intended for use when there is an error parsing a message,
389389
/// (so the Message object is unavailable) but an error message must be sent

src/NHapi.Base/Parser/ParserOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public ParserOptions()
66
{
77
DefaultObx2Type = null;
88
InvalidObx2Type = null;
9+
UnexpectedSegmentBehaviour = UnexpectedSegmentBehaviour.AddInline;
910
NonGreedyMode = false;
1011
}
1112

@@ -49,6 +50,12 @@ public ParserOptions()
4950
/// </example>
5051
public string InvalidObx2Type { get; set; }
5152

53+
/// <summary>
54+
/// Gets or Sets the behaviour to use when parsing a message and a nonstandard segment is found.
55+
/// </summary>
56+
/// <remarks>The default value is <see cref="Parser.UnexpectedSegmentBehaviour.AddInline"/>.</remarks>
57+
public UnexpectedSegmentBehaviour UnexpectedSegmentBehaviour { get; set; }
58+
5259
/// <summary>
5360
/// If set to <c>true</c> (default is <c>false</c>), pipe parser will be put in non-greedy mode. This setting
5461
/// applies only to <see cref="PipeParser"/> and will have no effect on <see cref="XMLParser"/>.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace NHapi.Base.Parser
2+
{
3+
using NHapi.Base.Model;
4+
5+
/// <summary>
6+
/// Defines the behaviour to use when an unexpected segment is discovered while parsing a message.
7+
/// </summary>
8+
/// <remarks>See <see cref="ParserOptions.UnexpectedSegmentBehaviour"/>.</remarks>
9+
public enum UnexpectedSegmentBehaviour
10+
{
11+
/// <summary>
12+
/// Add the segment as a <see cref="IGroup.AddNonstandardSegment(string, int)"/>
13+
/// at the current location, even if the current location is in a child group within the message.
14+
/// </summary>
15+
/// <remarks>This is the default.</remarks>
16+
AddInline,
17+
18+
/// <summary>
19+
/// Return the parser back to the root of the message (even if the last segment was in a group) and add
20+
/// the unexpected segment as a <see cref="IGroup.AddNonstandardSegment(string, int)"/>.
21+
/// </summary>
22+
DropToRoot,
23+
24+
/// <summary>
25+
/// Throw an <see cref="HL7Exception"/>
26+
/// </summary>
27+
ThrowHl7Exception,
28+
}
29+
}

src/NHapi.Base/Parser/XMLParser.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,12 @@ public virtual void Parse(IType datatypeObject, XmlElement datatypeElement)
389389
/// <summary> <p>Returns a minimal amount of data from a message string, including only the
390390
/// data needed to send a response to the remote system. This includes the
391391
/// following fields:
392-
/// <ul><li>field separator</li>
393-
/// <li>encoding characters</li>
394-
/// <li>processing ID</li>
395-
/// <li>message control ID</li></ul>
392+
/// <list type="bullet">
393+
/// <item><description>field separator</description></item>
394+
/// <item><description>encoding characters</description></item>
395+
/// <item><description>processing ID</description></item>
396+
/// <item><description>message control ID</description></item>
397+
/// </list>
396398
/// This method is intended for use when there is an error parsing a message,
397399
/// (so the Message object is unavailable) but an error message must be sent
398400
/// back to the remote system including some of the information in the inbound

src/NHapi.SourceGeneration/Generators/SegmentGenerator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ public static void MakeAll(string baseDirectory, string version)
155155
/// <summary>
156156
/// Returns an alternate segment name to replace the given segment name.
157157
/// Substitutions made include...
158-
/// <ul>
159-
/// <li>Replacing Z.. with Z</li>
160-
/// </ul>
158+
/// <list type="bullet">
159+
/// <item><description>Replacing Z.. with Z</description></item>
160+
/// </list>
161161
/// </summary>
162162
public static string AltSegName(string segmentName)
163163
{

0 commit comments

Comments
 (0)