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.
*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 packageList()
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().
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.
* * @param name name of the desired structure in the form XXX_YYY * @param version HL7 version (e.g. "2.3") * @param 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. * @return corresponding message subclass if found; GenericMessage otherwise */ public Class extends Message> getMessageClass(String theName, String theVersion, boolean isExplicit) throws HL7Exception { Class extends Message> mc = null; if (!isExplicit) { theName = Parser.getMessageStructureForEvent(theName, theVersion); } mc = (Class extends Message>) findClass(theName, theVersion, "message"); if (mc == null) mc = GenericMessage.getGenericMessageClass(theVersion); return mc; } public Class extends Message> getMessageClassInASpecificPackage(String theName, String theVersion, boolean isExplicit, String packageName) throws HL7Exception { Class extends Message> mc = null; if (!isExplicit) { theName = Parser.getMessageStructureForEvent(theName, theVersion); } mc = (Class extends Message>) findClassInASpecificPackage(theName, theVersion, "message", packageName); if (mc == null) mc = GenericMessage.getGenericMessageClass(theVersion); return mc; } /** * @see ca.uhn.hl7v2.parser.ModelClassFactory#getGroupClass(java.lang.String, java.lang.String) */ public Class extends Group> getGroupClass(String theName, String theVersion) throws HL7Exception { return (Class extends Group>) findClass(theName, theVersion, "group"); } /** * @see ca.uhn.hl7v2.parser.ModelClassFactory#getSegmentClass(java.lang.String, java.lang.String) */ public Class extends Segment> getSegmentClass(String theName, String theVersion) throws HL7Exception { return (Class extends Segment>) findClass(theName, theVersion, "segment"); } /** * @see ca.uhn.hl7v2.parser.ModelClassFactory#getTypeClass(java.lang.String, java.lang.String) */ public Class extends Type> getTypeClass(String theName, String theVersion) throws HL7Exception { return (Class extends Type>) findClass(theName, theVersion, "datatype"); } /** * Returns the path to the base package for model elements of the given version * - e.g. "ca/uhn/hl7v2/model/v24/". * This package should have the packages datatype, segment, group, and message * under it. The path ends in with a slash. */ public static String getVersionPackagePath(String ver) throws HL7Exception { if (Parser.validVersion(ver) == false) { throw new HL7Exception("The HL7 version " + ver + " is not recognized", HL7Exception.UNSUPPORTED_VERSION_ID); } StringBuffer path = new StringBuffer("ca/uhn/hl7v2/model/v"); char[] versionChars = new char[ver.length()]; ver.getChars(0, ver.length(), versionChars, 0); for (int i = 0; i < versionChars.length; i++) { if (versionChars[i] != '.') path.append(versionChars[i]); } path.append('/'); return path.toString(); } /** * Returns the package name for model elements of the given version - e.g. * "ca.uhn.hl7v2.model.v24.". This method * is identical togetVersionPackagePath(...)
except that path
* separators are replaced with dots.
*/
public static String getVersionPackageName(String ver) throws HL7Exception {
String path = DefaultModelClassFactory.getVersionPackagePath(ver);
String packg = path.replace('/', '.');
packg = packg.replace('\\', '.');
return packg;
}
/**
* Lists all the packages (user-definable) where classes for standard and custom * messages may be found. Each package has subpackages called "message", * "group", "segment", and "datatype" in which classes for these message elements * can be found.
*At a minimum, this method returns the standard package for the
* given version. For example, for version 2.4, the package list contains
* ca.uhn.hl7v2.model.v24
. In addition, user-defined packages may be specified
* for custom messages.
If you define custom message classes, and want Parsers to be able to
* find them, you must register them as follows (otherwise you will get an exception when
* the corresponding messages are parsed). For each HL7 version you want to support, you must
* put a text file on your classpath, under the folder /custom_packages, named after the version. For example,
* for version 2.4, you might put the file "custom_packages/2.4" in your application JAR. Each line in the
* file should name a package to search for message classes of that version. For example, if you
* work at foo.org, you might create a v2.4 message structure called "ZFO" and define it in the class
* org.foo.hl7.custom.message.ZFO
. In order for parsers to find this message
* class, you would need to enter the following line in custom_packages/2.4:
org.foo.hl7.custom
*Packages are searched in the order specified. The standard package for a given version * is searched last, allowing you to override the default implementation. Please note that * if you create custom classes for messages, segments, etc., their names must correspond exactly * to their names in the message text. For example, if you subclass the QBP segment in order to * add your own fields, your subclass must also be called QBP. although it will obviously be in * a different package. To make sure your class is used instead of the default implementation, * put your package in the package list. User-defined packages are searched first, so yours * will be found first and used.
*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 packageList()
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 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.
*/
public static String[] packageList(String version) throws HL7Exception {
//get package list for this version
return packages.get(version);
}
/**
* Returns a package list for the given version, including the standard package
* for that version and also user-defined packages (see packageList()).
*/
private static String[] loadPackages(String version) throws HL7Exception {
String[] retVal = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String customPackagesResourceName =
MessageFormat.format( CUSTOM_PACKAGES_RESOURCE_NAME_TEMPLATE, new Object[] { version } );
InputStream resourceInputStream = classLoader.getResourceAsStream( customPackagesResourceName );
List