Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PipeParser Enhancements - Fix issues related to unexpected segments. #200

Merged
merged 8 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 97 additions & 68 deletions src/NHapi.Base/Model/AbstractGroup.cs

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion src/NHapi.Base/Model/AbstractGroupItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ public class AbstractGroupItem
/// <param name="name"></param>
/// <param name="required"></param>
/// <param name="repeating"></param>
/// <param name="choiceElement"></param>
/// <param name="classType"></param>
public AbstractGroupItem(string name, bool required, bool repeating, Type classType)
public AbstractGroupItem(string name, bool required, bool repeating, bool choiceElement, Type classType)
{
Name = name;
IsRequired = required;
IsRepeating = repeating;
IsChoiceElement = choiceElement;
ClassType = classType;
}

Expand All @@ -43,6 +45,11 @@ public AbstractGroupItem(string name, bool required, bool repeating, Type classT
/// </summary>
public bool IsRequired { get; }

/// <summary>
/// Is item a "choice element".
/// </summary>
public bool IsChoiceElement { get; }

/// <summary>
/// The structures of the group item.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/NHapi.Base/Model/AbstractSegment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public virtual int GetTotalFieldRepetitionsUsed(int number)
public virtual IType GetField(int number, int rep)
{
EnsureEnoughFields(number);

if (number < 1 || number > items.Count)
{
throw new HL7Exception(
Expand Down
159 changes: 137 additions & 22 deletions src/NHapi.Base/Model/GenericMessage.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace NHapi.Base.Model
{
using System;
using System.Collections.Generic;

using NHapi.Base;
using NHapi.Base.Log;
Expand All @@ -13,6 +14,9 @@ namespace NHapi.Base.Model
/// <author>Bryan Tripp.</author>
public abstract class GenericMessage : AbstractMessage
{
// TODO: when we only target netstandard2.0 and above consider converting to ConcurrentDictionary
private static readonly Dictionary<string, Type> GenericMessages = new Dictionary<string, Type>();

/// <summary>
/// Creates a new instance of GenericMessage.
/// </summary>
Expand Down Expand Up @@ -54,31 +58,22 @@ public static Type GetGenericMessageClass(string version)
throw new ArgumentException($"The version {version} is not recognized");
}

// TODO: Think about converting this to a switch statement
Type c = null;
if (version.Equals("2.1"))
{
c = typeof(V21);
}
else if (version.Equals("2.2"))
{
c = typeof(V22);
}
else if (version.Equals("2.3"))
{
c = typeof(V23);
}
else if (version.Equals("2.3.1"))
Type c;
if (GenericMessages.ContainsKey(version))
{
c = typeof(V231);
c = GenericMessages[version];
}
else if (version.Equals("2.4"))
else
{
c = typeof(V24);
}
else if (version.Equals("2.5"))
{
c = typeof(V25);
var versionClassName = $"V{version.Replace(".", string.Empty)}";
var fullName = $"{typeof(GenericMessage).FullName}+{versionClassName}";

c = Type.GetType(fullName, false);

if (c != null)
{
GenericMessages.Add(version, c);
milkshakeuk marked this conversation as resolved.
Show resolved Hide resolved
}
}

return c;
Expand Down Expand Up @@ -203,5 +198,125 @@ public V25(IModelClassFactory factory)
/// </summary>
public override string Version => "2.5";
}

/// <summary>
/// Version 2.5.1 generic message.
/// </summary>
public class V251 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V251(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.5.1";
}

/// <summary>
/// Version 2.6 generic message.
/// </summary>
public class V26 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V26(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.6";
}

/// <summary>
/// Version 2.7 generic message.
/// </summary>
public class V27 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V27(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.7";
}

/// <summary>
/// Version 2.7.1 generic message.
/// </summary>
public class V271 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V271(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.7.1";
}

/// <summary>
/// Version 2.8 generic message.
/// </summary>
public class V28 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V28(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.8";
}

/// <summary>
/// Version 2.8.1 generic message.
/// </summary>
public class V281 : GenericMessage
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="factory"></param>
public V281(IModelClassFactory factory)
: base(factory)
{
}

/// <summary>
/// Version of message.
/// </summary>
public override string Version => "2.8.1";
}
}
}
66 changes: 54 additions & 12 deletions src/NHapi.Base/Model/IGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,36 +42,46 @@ namespace NHapi.Base.Model
/// </author>
public interface IGroup : IStructure
{
/// <summary> Returns an ordered array of the names of the Structures in this
/// Group. These names can be used to iterate through the group using
/// repeated calls to. <code>get(name)</code>.
/// <summary>
/// Returns an ordered array of the names of the Structures in this Group.
/// <para>
/// These names can be used to iterate through the group using repeated
/// calls to <see cref="GetStructure(string)"/>.
/// </para>
/// </summary>
string[] Names { get; }

/// <summary> Returns an array of Structure objects by name. For example, if the Group contains
/// an MSH segment and "MSH" is supplied then this call would return a 1-element array
/// containing the MSH segment. Multiple elements are returned when the segment or
/// group repeats. The array may be empty if no repetitions have been accessed
/// yet using the get(...) methods.
/// yet using the GetStructure(...) methods.
/// </summary>
/// <throws> HL7Exception if the named Structure is not part of this Group. </throws>
/// <param name="name">Name of the structure.</param>
/// <returns>Array of Structure objects.</returns>
/// <exception cref="HL7Exception">If the named Structure is not part of this Group.</exception>
IStructure[] GetAll(string name);

/// <summary> Returns the named structure. If this Structure is repeating then the first
/// repetition is returned. Creates the Structure if necessary.
/// </summary>
/// <throws> HL7Exception if the named Structure is not part of this Group. </throws>
/// <param name="name">Name of the structure.</param>
/// <returns>First (or only) structure object.</returns>
/// <exception cref="HL7Exception">If the named Structure is not part of this Group.</exception>
IStructure GetStructure(string name);

/// <summary> Returns a particular repetition of the named Structure. If the given repetition
/// number is one greater than the existing number of repetitions then a new
/// Structure is created.
/// </summary>
/// <throws> HL7Exception if the named Structure is not part of this group,. </throws>
/// <summary> if the structure is not repeatable and the given rep is > 0,
/// <param name="name">Name of the structure.</param>
/// <param name="rep">Repetition (zero-based).</param>
/// <returns>particular repetition of the named structure.</returns>
/// <exception cref="HL7Exception">if the named Structure is not part of this Group,
/// if the structure is not repeatable and the given rep is > 0,
/// or if the given repetition number is more than one greater than the
/// existing number of repetitions.
/// </summary>
/// </exception>
IStructure GetStructure(string name, int rep);

/// <summary> Returns true if the named structure is required. </summary>
Expand All @@ -80,6 +90,25 @@ public interface IGroup : IStructure
/// <summary> Returns true if the named structure is repeating. </summary>
bool IsRepeating(string name);

/// <summary>
/// Returns true if the named structure is a "choice element".
/// Some HL7 structures(e.g.ORM_O01 in v2.5) have groups that have
/// several possible first segments.In these structures, one of these
/// "choice elements" must be present, but not more than one.
/// </summary>
/// <param name="name">name of the structure nested in this group.</param>
/// <returns>true if structure is a choice element.</returns>
/// <exception cref="HL7Exception">if the named Structure is not part of this group.</exception>
bool IsChoiceElement(string name);

/// <summary>
/// Returns true if the named structure is a group.
/// </summary>
/// <param name="name">name of the structure nested in this group.</param>
/// <returns>true if structure is a choice element.</returns>
/// <exception cref="HL7Exception">if the named Structure is not part of this group.</exception>
bool IsGroup(string name);

/// <summary> Returns the Class of the Structure at the given name index. </summary>
Type GetClass(string name);

Expand All @@ -90,14 +119,27 @@ public interface IGroup : IStructure
Justification = "As this is a public member, we will duplicate the method and mark this one as obsolete.")]
string addNonstandardSegment(string name);

/// <summary>
/// Expands the group definition to include a segment that is not
/// defined by HL7 to be part of this group (eg: an unregistered Z segment).
/// <summary> Expands the group definition to include a segment that is not
/// defined by HL7 to be part of this group (eg an unregistered Z segment).
/// The new segment is slotted at the end of the group. Thenceforward if
/// such a segment is encountered it will be parsed into this location.
/// If the segment name is unrecognized a GenericSegment is used. The
/// segment is defined as repeating and not required.
/// </summary>
/// <param name="name">name of the segment.</param>
/// <exception cref="HL7Exception">Thrown when <see cref="IMessage.Version"/> returns null.</exception>
string AddNonstandardSegment(string name);

/// <summary> Expands the group definition to include a segment that is not
/// defined by HL7 to be part of this group (eg an unregistered Z segment).
/// The new segment is slotted at the end of the group. Thenceforward if
/// such a segment is encountered it will be parsed into this location.
/// If the segment name is unrecognized a GenericSegment is used. The
/// segment is defined as repeating and not required.
/// </summary>
/// <param name="name">name of the segment.</param>
/// <param name="index">index (zero-based) at which to insert this segment.</param>
/// <exception cref="HL7Exception">Thrown when <see cref="IMessage.Version"/> returns null.</exception>
string AddNonstandardSegment(string name, int index);
}
}
19 changes: 14 additions & 5 deletions src/NHapi.Base/Model/IStructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,28 @@ namespace NHapi.Base.Model
/// </author>
public interface IStructure
{
/// <summary> Returns the Message object to which this structure belongs. This should normally be set at
/// construction time. A Structure can only belong to a single Message. This is primarily
/// to avoid a situation where intended changes in one message cause unintended changes
/// <summary>
/// Returns the Message object to which this structure belongs.
/// <para>
/// This should normally be set at construction time.
/// </para>
/// <para>
/// A Structure can only belong to a single Message.
/// This is primarily to avoid a situation where intended changes in one message cause unintended changes
/// in another that shares one of the same Structure objects.
/// </para>
/// </summary>
IMessage Message { get; }

/// <summary> Returns the parent group within which this structure exists (may be root
/// <summary>
/// Returns the parent group within which this structure exists (may be root
/// message group).
/// </summary>
IGroup ParentStructure { get; }

/// <summary> Returns the structure's name. </summary>
/// <summary>
/// Returns the structure's name.
/// </summary>
string GetStructureName();
}
}
Loading