/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is part of dcm4che, an implementation of DICOM(TM) in
* Java(TM), hosted at https://github.com/gunterze/dcm4che.
*
* The Initial Developer of the Original Code is
* Agfa Healthcare.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* See @authors listed below
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.dcm4che3.hl7;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Gunter Zeilinger <gunterze@gmail.com>
*
*/
public class HL7Segment implements Serializable {
private static final long serialVersionUID = 2268883954083242976L;
private static final AtomicInteger nextMessageControlID =
new AtomicInteger(new Random().nextInt());
private final char fieldSeparator;
private final String encodingCharacters;
private String[] fields;
public HL7Segment(int size, char fieldSeparator, String encodingCharacters) {
if (size <= 0)
throw new IllegalArgumentException("size: " + size);
this.fieldSeparator = fieldSeparator;
this.encodingCharacters = encodingCharacters;
this.fields = new String[size];
}
public HL7Segment(int size) {
this(size, '|', "^~\\&");
}
public HL7Segment(String s, char fieldSeparator, String encodingCharacters) {
this.fieldSeparator = fieldSeparator;
this.encodingCharacters = encodingCharacters;
this.fields = split(s, fieldSeparator);
}
public final char getFieldSeparator() {
return fieldSeparator;
}
public final char getComponentSeparator() {
return encodingCharacters.charAt(0);
}
public final char getRepetitionSeparator() {
return encodingCharacters.charAt(1);
}
public final char getEscapeCharacter() {
return encodingCharacters.charAt(2);
}
public final char getSubcomponentSeparator() {
return encodingCharacters.charAt(3);
}
public final String getEncodingCharacters() {
return encodingCharacters;
}
public void setField(int index, String value) {
if (index >= fields.length)
fields = Arrays.copyOf(fields, index+1);
fields[index] = value;
}
public String getField(int index, String defVal) {
String val = index < fields.length ? fields[index] : null;
return val != null && !val.isEmpty() ? val : defVal;
}
public int size() {
return fields.length;
}
public String getSendingApplicationWithFacility() {
return getField(2, "") + '^' + getField(3, "");
}
public void setSendingApplicationWithFacility(String s) {
String[] ss = split(s, '^');
setField(2, ss[0]);
if (ss.length > 1)
setField(3, ss[1]);
}
public String getReceivingApplicationWithFacility() {
return getField(4, "") + '^' + getField(5, "");
}
public void setReceivingApplicationWithFacility(String s) {
String[] ss = split(s, '^');
setField(4, ss[0]);
if (ss.length > 1)
setField(5, ss[1]);
}
public String getMessageType() {
String s = getField(8, "").replace(getComponentSeparator(), '^');
int end = s.indexOf('^', s.indexOf('^') + 1);
return end > 0 ? s.substring(0, end) : s;
}
public String toString() {
return concat(fields, fieldSeparator);
}
public static String concat(String[] ss, char delim) {
int n = ss.length;
if (n == 0)
return "";
if (n == 1) {
String s = ss[0];
return s != null ? s : "";
}
int len = n - 1;
for (String s : ss)
if (s != null)
len += s.length();
char[] cs = new char[len];
for (int i = 0, off = 0; i < n; ++i) {
if (i != 0)
cs[off++] = delim;
String s = ss[i];
if (s != null) {
int l = s.length();
s.getChars(0, l, cs, off);
off += l;
}
}
return new String(cs);
}
public static String[] split(String s, char delim) {
int count = 1;
int delimPos = -1;
while ((delimPos = s.indexOf(delim, delimPos+1)) >= 0)
count++;
if (count == 1)
return new String[] { s };
String[] ss = new String[count];
int delimPos2 = s.length();
while (--count >= 0) {
delimPos = s.lastIndexOf(delim, delimPos2-1);
ss[count] = s.substring(delimPos+1, delimPos2);
delimPos2 = delimPos;
}
return ss;
}
public static HL7Segment parseMSH(byte[] b, int size) {
return parseMSH(b, size, new ParsePosition(0));
}
public static HL7Segment parseMSH(byte[] b, int size, ParsePosition pos) {
String s = parse(b, size, pos, null);
if (s.length() < 8)
throw new IllegalArgumentException("Invalid MSH Segment: " + s);
return new HL7Segment(s, s.charAt(3), s.substring(4,8));
}
static HL7Segment parse(byte[] b, int size, ParsePosition pos,
char fieldSeparator, String encodingCharacters, String charsetName) {
String s = parse(b, size, pos, charsetName);
return s != null
? new HL7Segment(s, fieldSeparator, encodingCharacters)
: null;
}
private static String parse(byte[] b, int size, ParsePosition pos,
String charsetName) {
int off = pos.getIndex();
int end = off;
while (end < size && b[end] != '\r' && b[end] != '\n')
end++;
int len = end - off;
if (len == 0)
return null;
if (++end < size && (b[end] == '\r' || b[end] == '\n'))
end++;
pos.setIndex(end);
try {
return charsetName != null
? new String(b, off, len, charsetName)
: new String(b, off, len);
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("charsetName: " + charsetName);
}
}
public static String nextMessageControlID() {
return Integer.toString(
nextMessageControlID.getAndIncrement() & 0x7FFFFFFF);
}
public static String timeStamp(Date date) {
return new SimpleDateFormat("yyyyMMddHHmmss.SSS").format(date);
}
public static HL7Segment makeMSH() {
return makeMSH(21, '|', "^~\\&");
}
public static HL7Segment makeMSH(int size, char fieldSeparator, String encodingCharacters) {
HL7Segment msh = new HL7Segment(size, fieldSeparator, encodingCharacters);
msh.setField(0, "MSH");
msh.setField(1, encodingCharacters);
msh.setField(6, timeStamp(new Date()));
msh.setField(9, nextMessageControlID());
msh.setField(10, "P");
msh.setField(11, "2.5");
return msh;
}
}