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 3 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
132 changes: 81 additions & 51 deletions src/NHapi.Base/Model/AbstractGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ protected internal AbstractGroup(IGroup parentStructure, IModelClassFactory fact
Init();
}

/// <summary> This constructor should only be used by classes that implement Message directly.
///
/// <summary>
/// This constructor should only be used by classes that implement Message directly.
/// </summary>
/// <param name="factory">the factory for classes of segments, groups, and datatypes under this group.
/// </param>
Expand All @@ -79,9 +79,7 @@ protected internal AbstractGroup(IModelClassFactory factory)
Init();
}

/// <summary>
/// A string[] of group names.
/// </summary>
/// <inheritdoc />
public virtual string[] Names
{
get
Expand All @@ -97,13 +95,13 @@ public virtual string[] Names
}
}

/// <summary> Returns the Message to which this segment belongs.</summary>
/// <inheritdoc />
public virtual IMessage Message
{
get
{
IStructure s = this;
while (!typeof(IMessage).IsAssignableFrom(s.GetType()))
while (!(s is IMessage))
{
s = s.ParentStructure;
}
Expand All @@ -112,28 +110,16 @@ public virtual IMessage Message
}
}

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

/// <summary> Returns the named structure. If this Structure is repeating then the first
/// repetition is returned. Creates the Structure if necessary.
/// </summary>
/// <exception cref="HL7Exception">Thrown when the named Structure is not part of this Group.</exception>
/// <inheritdoc />
public virtual IStructure GetStructure(string name)
{
return GetStructure(name, 0);
}

/// <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>
/// <exception cref="HL7Exception">Thrown when the named Structure is not part of this group or
/// 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.</exception>
/// <inheritdoc />
public virtual IStructure GetStructure(string name, int rep)
{
var item = GetGroupItem(name);
Expand Down Expand Up @@ -177,9 +163,13 @@ public virtual IStructure GetStructure(string name, int rep)
return ret;
}

/// <summary> Adds a new item to the Structure. </summary>
/// <exception cref="HL7Exception">Thrown when the named Structure is not part of this group
/// or if the structure is not repeatable and an item already exists. </exception>
/// <summary>
/// Adds a new item to the Structure.
/// </summary>
/// <exception cref="HL7Exception">
/// Thrown when the named Structure is not part of this group
/// or if the structure is not repeatable and an item already exists.
/// </exception>
public virtual IStructure AddStructure(string name)
{
var item = GetGroupItem(name);
Expand Down Expand Up @@ -207,8 +197,12 @@ public virtual IStructure AddStructure(string name)
return ret;
}

/// <summary> Removes the given structure from the named Structure. </summary>
/// <exception cref="HL7Exception">Thrown when the named Structure is not part of this Group.</exception>
/// <summary>
/// Removes the given structure from the named Structure.
/// </summary>
/// <exception cref="HL7Exception">
/// Thrown when the named Structure is not part of this Group.
/// </exception>
public virtual void RemoveStructure(string name, IStructure toRemove)
{
var item = GetGroupItem(name);
Expand Down Expand Up @@ -253,14 +247,7 @@ public virtual string addNonstandardSegment(string name)
return AddNonstandardSegment(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>
/// <exception cref="HL7Exception">Thrown when 'Message.Version' returns null.</exception>
/// <inheritdoc />
public virtual string AddNonstandardSegment(string name)
{
var version = Message.Version;
Expand All @@ -269,20 +256,37 @@ public virtual string AddNonstandardSegment(string name)
throw new HL7Exception("Need message version to add segment by name; message.getVersion() returns null");
}

var c = myFactory.GetSegmentClass(name, version);
if (c == null)
var c = myFactory.GetSegmentClass(name, version) ?? typeof(GenericSegment);

var index = Names.Length;

TryToInstantiateStructure(c, name); // may throw exception

return Insert(c, false, true, false, index, name);
milkshakeuk marked this conversation as resolved.
Show resolved Hide resolved
}

/// <inheritdoc />
public virtual string AddNonstandardSegment(string name, int index)
{
if (this is IMessage && index == 0)
{
c = typeof(GenericSegment);
throw new HL7Exception($"Can not add nonstandard segment \"{name}\" to start of message.");
milkshakeuk marked this conversation as resolved.
Show resolved Hide resolved
}

var index = Names.Length;
var version = Message.Version;
if (version == null)
{
throw new HL7Exception("Need message version to add segment by name; message.getVersion() returns null");
}

var c = myFactory.GetSegmentClass(name, version) ?? typeof(GenericSegment);

TryToInstantiateStructure(c, name); // may throw exception

return Insert(c, false, true, index, name);
return Insert(c, false, true, false, index, name);
milkshakeuk marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary> Returns true if the named structure is required. </summary>
/// <inheritdoc />
public virtual bool IsRequired(string name)
{
var item = GetGroupItem(name);
Expand All @@ -296,7 +300,7 @@ public virtual bool IsRequired(string name)
return item.IsRequired;
}

/// <summary> Returns true if the named structure is required. </summary>
/// <inheritdoc />
public virtual bool IsRepeating(string name)
{
var item = GetGroupItem(name);
Expand All @@ -310,6 +314,34 @@ public virtual bool IsRepeating(string name)
return item.IsRepeating;
}

/// <inheritdoc />
public virtual bool IsChoiceElement(string name)
{
var item = GetGroupItem(name);
if (item == null)
{
throw new HL7Exception(
$"The structure {name} does not exist in the group {GetType().FullName}",
ErrorCode.APPLICATION_INTERNAL_ERROR);
}

return item.IsChoiceElement;
}

/// <inheritdoc />
public virtual bool IsGroup(string name)
{
var item = GetGroupItem(name);
if (item == null)
{
throw new HL7Exception(
$"The structure {name} does not exist in the group {GetType().FullName}",
ErrorCode.APPLICATION_INTERNAL_ERROR);
}

return typeof(IGroup).IsAssignableFrom(item.ClassType);
}

[Obsolete("This method has been replaced by 'CurrentReps'.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
Expand Down Expand Up @@ -400,7 +432,7 @@ protected internal virtual string Add(Type c, bool required, bool repeating)
{
var name = GetStructureName(c);

return Insert(c, required, repeating, items.Count, name);
return Insert(c, required, repeating, false, items.Count, name);
}

/// <summary>
Expand Down Expand Up @@ -434,7 +466,7 @@ private void Init()
/// of the group's normal children should be done at construction time, using the
/// add(...) method.
/// </summary>
private string Insert(Type classType, bool required, bool repeating, int index, string name)
private string Insert(Type classType, bool required, bool repeating, bool choiceElement, int index, string name)
{
// see if there is already something by this name and make a new name if necessary ...
if (NameExists(name))
Expand All @@ -449,7 +481,7 @@ private string Insert(Type classType, bool required, bool repeating, int index,
name = newName;
}

var item = new AbstractGroupItem(name, required, repeating, classType);
var item = new AbstractGroupItem(name, required, repeating, choiceElement, classType);
items.Insert(index, item);
return name;
}
Expand All @@ -476,10 +508,9 @@ private bool NameExists(string name)
/// </param>
private IStructure TryToInstantiateStructure(Type c, string name)
{
IStructure s = null;
IStructure s;
try
{
object o = null;
if (typeof(GenericSegment).IsAssignableFrom(c))
{
s = new GenericSegment(this, name);
Expand All @@ -491,6 +522,7 @@ private IStructure TryToInstantiateStructure(Type c, string name)
else
{
// first try to instantiate using constructor w/ Message arg ...
object o;
try
{
var argClasses = new Type[] { typeof(IGroup), typeof(IModelClassFactory) };
Expand Down Expand Up @@ -519,10 +551,8 @@ private IStructure TryToInstantiateStructure(Type c, string name)
{
throw (HL7Exception)e;
}
else
{
throw new HL7Exception("Can't instantiate class " + c.FullName, ErrorCode.APPLICATION_INTERNAL_ERROR, e);
}

throw new HL7Exception("Can't instantiate class " + c.FullName, ErrorCode.APPLICATION_INTERNAL_ERROR, e);
milkshakeuk marked this conversation as resolved.
Show resolved Hide resolved
}

return s;
Expand Down
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
Loading