/// <summary> /// Note that the validation context of the resulting message is set to this parsers validation /// context. The validation context is used within <see cref="IPrimitive.Value"/>. /// </summary> /// <param name="theName">name of the desired structure in the form XXX_YYY.</param> /// <param name="theVersion">HL7 version (e.g. "2.3").</param> /// <param name="isExplicit"> /// true if the structure was specified explicitly in MSH-9-3, false if it /// was inferred from MSH-9-1 and MSH-9-2. If false, a lookup may be performed to find /// an alternate structure corresponding to that message type and event. /// </param> /// <returns>a Message instance.</returns> /// <exception cref="HL7Exception">Thrown when the version is not recognized or no appropriate class can be found or the Message.</exception> protected internal virtual IMessage InstantiateMessage(string theName, string theVersion, bool isExplicit) { Type messageClass; try { messageClass = Factory.GetMessageClass(theName, theVersion, isExplicit); } catch (Exception ex) { throw new HL7Exception( $"Can't find message class in current package list: {theName}", ErrorCode.UNSUPPORTED_MESSAGE_TYPE, ex); } if (messageClass == null) { throw new HL7Exception( $"Can't find message class in current package list: {theName}", ErrorCode.UNSUPPORTED_MESSAGE_TYPE); } Log.Info($"Instantiating msg of class {messageClass.FullName}"); var constructor = messageClass.GetConstructor(new Type[] { typeof(IModelClassFactory) }); var result = (IMessage)constructor.Invoke(new object[] { Factory }); result.ValidationContext = validationContext; return(result); }
/// <summary> Note that the validation context of the resulting message is set to this parser's validation /// context. The validation context is used within Primitive.setValue(). /// /// </summary> /// <param name="name">name of the desired structure in the form XXX_YYY /// </param> /// <param name="version">HL7 version (e.g. "2.3") /// </param> /// <param name="isExplicit">true if the structure was specified explicitly in MSH-9-3, false if it /// was inferred from MSH-9-1 and MSH-9-2. If false, a lookup may be performed to find /// an alternate structure corresponding to that message type and event. /// </param> /// <returns> a Message instance /// </returns> /// <throws> HL7Exception if the version is not recognized or no appropriate class can be found or the Message </throws> /// <summary> class throws an exception on instantiation (e.g. if args are not as expected) /// </summary> protected internal virtual IMessage InstantiateMessage(System.String theName, System.String theVersion, bool isExplicit) { IMessage result = null; System.Type messageClass = _modelClassFactory.GetMessageClass(theName, theVersion, isExplicit); if (messageClass == null) { throw new System.Exception("Can't find message class in current package list: " + theName); } _log.Info("Instantiating msg of class " + messageClass.FullName); System.Reflection.ConstructorInfo constructor = messageClass.GetConstructor(new System.Type[] { typeof(IModelClassFactory) }); result = (IMessage)constructor.Invoke(new System.Object[] { _modelClassFactory }); result.ValidationContext = _validationContext; return(result); }
/// <summary> Sets the next position to a new segment of the given name, within the /// given group. /// </summary> private void newSegment(IGroup parent, System.String name) { log.Info("MessageIterator creating new segment: " + name); parent.addNonstandardSegment(name); next_Renamed_Field = new Position(parent, parent.Names[parent.Names.Length - 1], 0); }
/// <summary> <p>Given a list of structures defining the deep content of a group (as provided in /// the normative database, some being pairs of optionality and repetition markers /// and segments nested within) returns a GroupDef including a short list of the shallow contents of the /// group (including segments and groups that are immediate children).</p> /// <p>For example given MSH [PID PV1] {[ERR NTE]}, short list would be something like /// MSH PID_GROUP ERR_GROUP (with PID_GROUP marked as optional and ERR_GROUP marked as /// optional and repeating).</p> /// <p>This method calls writeGroup(...) where necessary in order to create source code for /// any nested groups before returning corresponding GroupDefs.</p> /// </summary> public static GroupDef GetGroupDef( IStructureDef[] structures, string groupName, string baseDirectory, string version, string message) { GroupDef ret; var required = true; var repeating = false; var rep_opt = false; var len = structures.Length; var shortList = new IStructureDef[len]; // place to put final list of groups/segments w/o opt & rep markers var currShortListPos = 0; try { // check for rep and opt (see if start & end elements are [] or {} AND they are each others' pair) ... // System.out.println(len + " " + structures[0].getName() +structures[1].getName()+ ".." +structures[len-2].getName() + structures[len-1].getName()+ " " + message); if (OptMarkers(structures[0].Name, structures[len - 1].Name) && (FindGroupEnd(structures, 0) == len - 1)) { required = false; } if (RepMarkers(structures[0].Name, structures[len - 1].Name) && (FindGroupEnd(structures, 0) == len - 1)) { repeating = true; } if (RepoptMarkers(structures[0].Name, structures[len - 1].Name) && (FindGroupEnd(structures, 0) == len - 1)) { rep_opt = true; } if (repeating || !required) { if (OptMarkers(structures[1].Name, structures[len - 2].Name) && (FindGroupEnd(structures, 1) == len - 2)) { required = false; } if (RepMarkers(structures[1].Name, structures[len - 2].Name) && (FindGroupEnd(structures, 1) == len - 2)) { repeating = true; } } // loop through, recurse nested groups, and build short list of structures for this group var skip = 0; if (!required) { skip++; } if (repeating) { skip++; } if (rep_opt) { skip++; } var currLongListPos = skip; while (currLongListPos < len - skip) { var currSegName = structures[currLongListPos].Name; if (currSegName.Equals("[") || currSegName.Equals("{") || currSegName.Equals("[{")) { // this is the opening of a new group ... var name = ((SegmentDef)structures[currLongListPos]).GroupName; // Fix mistakes in DB (ported from hapi) // Fix github issue https://github.com/nHapiNET/nHapi/issues/298 if (name is not null) { if (groupName == "OBSERVATION_REQUEST" && message == "ORL_O34" && name == "SPECIMEN" && version == "2.5.1") { name = "OBSERVATION_REQUEST_SPECIMEN"; } } var endOfNewGroup = FindGroupEnd(structures, currLongListPos); var newGroupStructures = new IStructureDef[endOfNewGroup - currLongListPos + 1]; Array.Copy(structures, currLongListPos, newGroupStructures, 0, newGroupStructures.Length); shortList[currShortListPos] = WriteGroup(newGroupStructures, name, baseDirectory, version, message); currLongListPos = endOfNewGroup + 1; } else { // copy verbatim into short list ... shortList[currShortListPos] = structures[currLongListPos]; currLongListPos++; } currShortListPos++; } } catch (ArgumentException e) { throw new HL7Exception( "Problem creating nested group: " + e.GetType().FullName + ": " + e.Message, ErrorCode.APPLICATION_INTERNAL_ERROR); } if (rep_opt) { ret = new GroupDef(message, groupName, false, true, "a Group object"); } else { ret = new GroupDef(message, groupName, required, repeating, "a Group object"); } var finalList = new IStructureDef[currShortListPos]; // note: incremented after last assignment Array.Copy(shortList, 0, finalList, 0, currShortListPos); foreach (var structureDef in finalList) { // Fix mistakes in the DB (ported from hapi) if (structureDef.UnqualifiedName == "ED") { continue; } // Fix github issue https://github.com/nHapiNET/nHapi/issues/298 if (ret.UnqualifiedName == "OBSERVATION_REQUEST" && message == "ORL_O34" && structureDef.UnqualifiedName == "SPECIMEN" && version == "2.5.1") { ((GroupDef)structureDef).GroupName = "OBSERVATION_REQUEST_SPECIMEN"; Log.Info($"Forcing name to {((GroupDef)structureDef).GroupName}"); } ret.AddStructure(structureDef); } return(ret); }