Wraps a message to provide access to fields using a terse location specification syntax. For example:
terser.set("MSH-9-3", "ADT_A01");
can be used instead of
message.getMSH().getMessageType().getMessageStructure().setValue("ADT_A01");
The syntax of a location spec is as follows:
location_spec: segment_path_spec "-" field ["(" rep ")"] ["-" component ["-" subcomponent]]
... where rep, field, component, and subcomponent are integers (representing, respectively, the field repetition (starting at 0), and the field number, component number, and subcomponent numbers (starting at 1). Omitting the rep is equivalent to specifying 0; omitting the component or subcomponent is equivalent to specifying 1.
The syntax for the segment_path_spec is as follows:
segment_path_spec: ["/"] (group_spec ["(" rep ")"] "/")* segment_spec ["(" rep ")"]
... where rep has the same meaning as for fields.
A leading "/" indicates that navigation to the location begins at the root of the message; omitting this indicates that navigation begins at the current location of the underlying SegmentFinder (see getFinder() -- this allows manual navigation if desired). The syntax for group_spec is:
group_spec: ["."] group_name_pattern
Here, a . indicates that the group should be searched for (using a SegmentFinder) starting at the current location in the message. The wildcards "*" and "?" represent any number of arbitrary characters, and a single arbitrary character, respectively. For example, "M*" and "?S?" match MSH. The first group with a name that matches the given group_name_pattern will be matched.
The segment_spec is analogous to the group_spec.
As another example, the following subcomponent in an SIU_S12 message:
msg.getSIU_S12_RGSAISNTEAIGNTEAILNTEAIPNTE(1).getSIU_S12_AIGNTE().getAIG().getResourceGroup(1).getIdentifier();
/SIU_S12_RGSAISNTEAIGNTEAILNTEAIPNTE(1)/SIU_S12_AIGNTE/AIG-5(1)-1
/*AIG*(1)/SIU_S12_AIGNTE/AIG-5(1)-1
/*AIG*(1)/.AIG-5(1)
The search function only iterates through rep 0 of each group. Thus if rep 0 of the first group in this example was desired instead of rep 1, the following syntax would also work (since there is only one AIG segment position in SUI_S12):
/.AIG-5(1)
@author Bryan Tripp
@author Ryan W. Gross (General Electric Corporation - Healthcare IT).
throw new HL7Exception("Can't encode null message",
HL7Exception.REQUIRED_FIELD_MISSING);
}
// register message with response Receiver(s) (by message ID)
Terser t = new Terser(out);
String messID = t.get("/MSH-10");
if (messID == null || messID.length() == 0) {
throw new HL7Exception(
"MSH segment missing required field Control ID (MSH-10)",
HL7Exception.REQUIRED_FIELD_MISSING);
try {
// get message ID
String ID = MessageIDGenerator.getInstance()
.getNewID();
Message out = parser.parse(outText);
Terser tOut = new Terser(out);
tOut.set("/MSH-10", ID);
// send, get response
Message in = initiator.sendAndReceive(out);
// get ACK ID
Terser tIn = new Terser(in);
String ackID = tIn.get("/MSA-2");
if (ID.equals(ackID)) {
System.out.println("OK - ack ID matches");
} else {
throw new RuntimeException(
"Ack ID for message " + ID + " is "
// create error message ...
String errorMessage = null;
try {
Message out = DefaultApplication.makeACK(inHeader);
Terser t = new Terser(out);
// copy required data from incoming message ...
try {
t.set("/MSH-10", MessageIDGenerator.getInstance().getNewID());
} catch (IOException ioe) {
throw new HL7Exception("Problem creating error message ID: "
+ ioe.getMessage());
}
// populate MSA ...
t.set("/MSA-1", "AE"); // should this come from HL7Exception
// constructor?
t.set("/MSA-2", Terser.get(inHeader, 10, 0, 1, 1));
String excepMessage = e.getMessage();
if (excepMessage != null)
t.set("/MSA-3",
excepMessage.substring(0,
Math.min(80, excepMessage.length())));
/*
* Some earlier ACKs don't have ERRs, but I think we'll change this
* within HAPI so that there is a single ACK for each version (with
* an ERR).
*/
// see if it's an HL7Exception (so we can get specific information)
// ...
if (e.getClass().equals(HL7Exception.class)) {
// Segment err = (Segment) out.get("ERR");
// ((HL7Exception) e).populate(err); // FIXME: this is broken,
// it relies on the database in a place where it's not available
} else {
t.set("/ERR-1-4-1", "207");
t.set("/ERR-1-4-2", "Application Internal Error");
t.set("/ERR-1-4-3", "HL70357");
}
if (encoding != null) {
errorMessage = p.encode(out, encoding);
} else {
String version = inbound.getVersion();
if (version == null)
version = "2.4"; // TODO: This should be set dynamically based on available HL7 version
clazz = mcf.getMessageClass("ACK", version, false);
Message out = clazz.newInstance();
Terser terser = new Terser(out);
// populate outbound MSH using data from inbound message ...
Segment outHeader = (Segment) out.get("MSH");
fillResponseHeader(inboundHeader, outHeader);
terser.set("/MSH-9-1", "ACK");
terser.set("/MSH-9-2", Terser.get(inboundHeader, 9, 0, 2, 1));
terser.set("/MSH-12", Terser.get(inboundHeader, 12, 0, 1, 1));
terser.set("/MSA-1", "AA");
terser.set("/MSA-2", Terser.get(inboundHeader, 10, 0, 1, 1));
return out;
} catch (Exception e) {
throw new HL7Exception("Can't instantiate ACK", e);
}
* the type and trigger event of the given message, or null if there are
* none.
*/
private Application getMatchingApplication(Message message)
throws HL7Exception {
Terser t = new Terser(message);
String messageType = t.get("/MSH-9-1");
String triggerEvent = t.get("/MSH-9-2");
return this.getMatchingApplication(messageType, triggerEvent);
}
}
private void parse(StringTokenizer tok, Message message, StructRef root, EncodingCharacters ec)
throws HL7Exception {
Terser t = new Terser(message);
synchronized (root) {
StructRef ref = root.getSuccessor("MSH");
int field = 0;
Segment segment = null;
int[] fields = new int[0];
while (tok.hasMoreTokens()) {
String token = tok.nextToken();
if (token.charAt(0) == ec.getFieldSeparator()) {
field++;
} else if (token.charAt(0) == ourSegmentSeparator) {
field = 0;
} else if (field == 0) {
StructRef newref = drill(ref, token);
if (newref == null) {
segment = null;
fields = new int[0];
} else {
ref = newref;
ourLog.debug("Parsing into segment {}", ref.getFullPath());
segment = t.getSegment(ref.getFullPath());
fields = ref.getFields();
}
} else if (segment != null && Arrays.binarySearch(fields, field) >= 0) {
parse(token, segment, field, ec);
}
return (ValidationException[]) problems.toArray(new ValidationException[0]);
}
private String[] getDeclaredProfileIDs(Message theMessage) throws HL7Exception {
Terser t = new Terser(theMessage);
boolean noMore = false;
int c = 0;
List<String> declaredProfiles = new ArrayList<String>(8);
while (!noMore) {
String path = "MSH-21(" + c++ + ")";
String idRep = t.get(path);
//FIXME fails if empty rep precedes full rep ... should add getAll() to Terser and use that
if (idRep == null || idRep.equals("")) {
noMore = true;
} else {
declaredProfiles.add(idRep);
return handler.result();
}
private void testMessageRules(Message message, ValidationExceptionHandler<R> handler)
throws HL7Exception {
Terser t = new Terser(message);
String messageType = t.get("MSH-9-1");
String triggerEvent = t.get("MSH-9-2");
List<MessageRule> rules = new ArrayList<MessageRule>();
if (getValidationContext() != null) {
rules.addAll(getValidationContext().getMessageRules(message.getVersion(), messageType,
triggerEvent));
}
LoggerFactory.getLogger(logName).error("message validation failure", problems[i]);
}
}
private void addProblemsToACK(Message ack, HL7Exception[] problems) throws HL7Exception {
Terser t = new Terser(ack);
if (problems.length > 0) {
t.set("MSA-1", "AE");
t.set("MSA-3", "Errors were encountered while testing the message");
}
/*
Segment err = (Segment) ack.get("ERR");
for (int i = 0; i < problems.length; i++) {
// problems[i].populate(err); FIXME: broken! needs database
throw new HL7Exception("Can't encode null message",
ErrorCode.REQUIRED_FIELD_MISSING);
}
// register message with response Receiver(s) (by message ID)
Terser t = new Terser(out);
String messID = t.get("/MSH-10");
if (messID == null || messID.length() == 0) {
throw new HL7Exception(
"MSH segment missing required field Control ID (MSH-10)",
ErrorCode.REQUIRED_FIELD_MISSING);
Related Classes of ca.uhn.hl7v2.util.Terser
Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.