/// <summary>Creates a new instance of Server </summary> public NuGenHL7Service(NuGenParser parser, LowerLayerProtocol llp) { connections = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); listeners = new System.Collections.ArrayList(); this.parser = parser; this.llp = llp; this.router = new NuGenMessageTypeRouter(); }
/// <summary> <p>Attempts to return the message class corresponding to the given name, by /// searching through default and user-defined (as per packageList()) packages. /// Returns GenericMessage if the class is not found.</p> /// <p>It is important to note that there can only be one implementation of a particular message /// structure (i.e. one class with the message structure name, regardless of its package) among /// the packages defined as per the <code>packageList()</code> method. If there are duplicates /// (e.g. two ADT_A01 classes) the first one in the search order will always be used. However, /// this restriction only applies to message classes, not (normally) segment classes, etc. This is because /// classes representing parts of a message are referenced explicitly in the code for the message /// class, rather than being looked up (using findMessageClass() ) based on the String value of MSH-9. /// The exception is that Segments may have to be looked up by name when they appear /// in unexpected locations (e.g. by local extension) -- see findSegmentClass().</p> /// <p>Note: the current implementation will be slow if there are multiple user- /// defined packages, because the JVM will try to load a number of non-existent /// classes every parse. This should be changed so that specific classes, rather /// than packages, are registered by name.</p> /// /// </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> corresponding message subclass if found; GenericMessage otherwise /// </returns> public virtual System.Type getMessageClass(System.String theName, System.String theVersion, bool isExplicit) { System.Type mc = null; if (!isExplicit) { theName = NuGenParser.getMessageStructureForEvent(theName, theVersion); } mc = findClass(theName, theVersion, "message"); if (mc == null) { mc = GenericMessage.getGenericMessageClass(theVersion); } return(mc); }
/// <summary> <p>Returns a minimal amount of data from a message string, including only the /// data needed to send a response to the remote system. This includes the /// following fields: /// <ul><li>field separator</li> /// <li>encoding characters</li> /// <li>processing ID</li> /// <li>message control ID</li></ul> /// This method is intended for use when there is an error parsing a message, /// (so the Message object is unavailable) but an error message must be sent /// back to the remote system including some of the information in the inbound /// message. This method parses only that required information, hopefully /// avoiding the condition that caused the original error.</p> /// </summary> public override Segment getCriticalResponseData(System.String message) { System.String version = getVersion(message); Segment criticalData = NuGenParser.makeControlMSH(version, Factory); Terser.set_Renamed(criticalData, 1, 0, 1, 1, parseLeaf(message, "MSH.1", 0)); Terser.set_Renamed(criticalData, 2, 0, 1, 1, parseLeaf(message, "MSH.2", 0)); Terser.set_Renamed(criticalData, 10, 0, 1, 1, parseLeaf(message, "MSH.10", 0)); System.String procID = parseLeaf(message, "MSH.11", 0); if (procID == null || procID.Length == 0) { procID = parseLeaf(message, "PT.1", message.IndexOf("MSH.11")); //this field is a composite in later versions } Terser.set_Renamed(criticalData, 11, 0, 1, 1, procID); return(criticalData); }
/// <summary> Finds a message or segment class by name and version.</summary> /// <param name="name">the segment or message structure name /// </param> /// <param name="version">the HL7 version /// </param> /// <param name="type">'message', 'group', 'segment', or 'datatype' /// </param> private static System.Type findClass(System.String name, System.String version, System.String type) { if (NuGenParser.validVersion(version) == false) { throw new NuGenHL7Exception("The HL7 version " + version + " is not recognized", NuGenHL7Exception.UNSUPPORTED_VERSION_ID); } //get list of packages to search for the corresponding message class System.String[] packages = packageList(version); //get subpackage for component type System.String types = "message|group|segment|datatype"; if (types.IndexOf(type) < 0) { throw new NuGenHL7Exception("Can't find " + name + " for version " + version + " -- type must be " + types + " but is " + type); } System.String subpackage = type; //try to load class from each package System.Type compClass = null; int c = 0; while (compClass == null && c < packages.Length) { try { System.String p = packages[c]; if (!p.EndsWith(".")) { p = p + "."; } System.String classNameToTry = p + subpackage + "." + name; compClass = System.Type.GetType(classNameToTry); } catch (System.Exception) { /* just try next one */ } c++; } return(compClass); }
/// <summary> Checks the encoding of the message using getEncoding(), and returns the corresponding /// parser (either pipeParser or xmlParser). If the encoding is not recognized an /// HL7Exception is thrown. /// </summary> private NuGenParser getAppropriateParser(System.String message) { System.String encoding = getEncoding(message); if (encoding == null) { encoding = ""; //prevent null pointer exception } NuGenParser appropriateParser = null; if (encoding.ToUpper().Equals("VB".ToUpper())) { appropriateParser = pipeParser; } else if (encoding.ToUpper().Equals("XML".ToUpper())) { appropriateParser = xmlParser; } else { throw new NuGenHL7Exception("Can't find appropriate parser - encoding not recognized", NuGenHL7Exception.APPLICATION_INTERNAL_ERROR); } return(appropriateParser); }
/// <summary> Sets the underlying PipeParser as the primary parser, so that subsequent calls to /// encode() will return traditionally encoded messages, and an attempt will be made to use the /// PipeParser first for parsing. This is the default setting. /// </summary> public virtual void setPipeParserAsPrimary() { primaryParser = pipeParser; secondaryParser = xmlParser; }