Initial Commit
This commit is contained in:
commit
b7c84d0f95
|
@ -0,0 +1,4 @@
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*/target/
|
||||||
|
target/
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2016 Travis Burtrum.
|
||||||
|
~
|
||||||
|
~ Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
~ GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
~ applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
~ file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
~ of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
~ and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
~ If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
~ this file under either the MPL or the GPL.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.sonatype.oss</groupId>
|
||||||
|
<artifactId>oss-parent</artifactId>
|
||||||
|
<version>9</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.moparisthebest.hl7</groupId>
|
||||||
|
<artifactId>SimpleHL7</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>
|
||||||
|
This project makes creating, parsing, sending and recieving HL7 messages simple.
|
||||||
|
</description>
|
||||||
|
<url>https://github.com/moparisthebest/SimpleHL7</url>
|
||||||
|
<organization>
|
||||||
|
<name>moparisthebest.com</name>
|
||||||
|
<url>https://www.moparisthebest.com</url>
|
||||||
|
</organization>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>moparisthebest</id>
|
||||||
|
<name>Travis Burtrum</name>
|
||||||
|
<email>admin@moparisthebest.com</email>
|
||||||
|
<url>https://www.moparisthebest.com/</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:https://github.com/moparisthebest/SimpleHL7.git</connection>
|
||||||
|
<developerConnection>scm:git:https://github.com/moparisthebest/SimpleHL7.git</developerConnection>
|
||||||
|
<url>https://github.com/moparisthebest/SimpleHL7</url>
|
||||||
|
</scm>
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>Mozilla Public License Version 1.1</name>
|
||||||
|
<url>https://www.mozilla.org/en-US/MPL/1.1/</url>
|
||||||
|
</license>
|
||||||
|
<license>
|
||||||
|
<name>GNU General Public License, Version 3</name>
|
||||||
|
<url>https://www.gnu.org/licenses/gpl-3.0.html</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
<properties>
|
||||||
|
<maven.test.skip>true</maven.test.skip>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<pushChanges>false</pushChanges>
|
||||||
|
<localCheckout>true</localCheckout>
|
||||||
|
</properties>
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<debug>true</debug>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<serverId>ossrh</serverId>
|
||||||
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.7</version>
|
||||||
|
<configuration>
|
||||||
|
<additionalparam>-Xdoclint:none</additionalparam>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>run-tests</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>maven.test.skip</name>
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
public class Component extends SubComponentContainer<SubComponent> {
|
||||||
|
|
||||||
|
Component() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component(final String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component(final String s, final Encoding enc) {
|
||||||
|
super(s, enc, enc.subComponentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SubComponent newSubComponent() {
|
||||||
|
return new SubComponentImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SubComponent newSubComponent(final String s) {
|
||||||
|
return new SubComponentImpl(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SubComponent newSubComponent(final String s, final Encoding enc) {
|
||||||
|
return new SubComponentImpl(s, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
super.encode(sb, enc, enc.subComponentDelimiter, enc.componentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int index) {
|
||||||
|
return super.subComponent1Based(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
public SubComponent sc(final int index) {
|
||||||
|
return this.subComponent(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString("SubComponent");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Encoding extends Field {
|
||||||
|
public final char segmentDelimiter, repetitionDelimiter, fieldDelimiter, componentDelimiter, subComponentDelimiter, escapeCharacter, verticalTab, fileSeperator;
|
||||||
|
public final String repetitionEscape, fieldEscape, componentEscape, subComponentEscape, escapeEscape;
|
||||||
|
|
||||||
|
private final String repetitionDelimiterString, fieldDelimiterString, componentDelimiterString, subComponentDelimiterString, escapeCharacterString, value;
|
||||||
|
|
||||||
|
public final MSH1 msh1;
|
||||||
|
|
||||||
|
// '\r', '~', '|', '^', '&', '\\'
|
||||||
|
public Encoding(final char segmentDelimiter, final char repetitionDelimiter, final char fieldDelimiter, final char componentDelimiter, final char subComponentDelimiter, final char escapeCharacter) {
|
||||||
|
this(segmentDelimiter, repetitionDelimiter, fieldDelimiter, componentDelimiter, subComponentDelimiter, escapeCharacter, (char) 11, (char) 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Encoding(final char segmentDelimiter, final char repetitionDelimiter, final char fieldDelimiter, final char componentDelimiter, final char subComponentDelimiter, final char escapeCharacter, final char verticalTab, final char fileSeperator) {
|
||||||
|
this.segmentDelimiter = segmentDelimiter;
|
||||||
|
this.repetitionDelimiter = repetitionDelimiter;
|
||||||
|
this.fieldDelimiter = fieldDelimiter;
|
||||||
|
this.componentDelimiter = componentDelimiter;
|
||||||
|
this.subComponentDelimiter = subComponentDelimiter;
|
||||||
|
this.escapeCharacter = escapeCharacter;
|
||||||
|
this.verticalTab = verticalTab;
|
||||||
|
this.fileSeperator = fileSeperator;
|
||||||
|
|
||||||
|
this.repetitionEscape = escapeCharacter + "R" + escapeCharacter;
|
||||||
|
this.fieldEscape = escapeCharacter + "F" + escapeCharacter;
|
||||||
|
this.componentEscape = escapeCharacter + "S" + escapeCharacter;
|
||||||
|
this.subComponentEscape = escapeCharacter + "T" + escapeCharacter;
|
||||||
|
this.escapeEscape = escapeCharacter + "E" + escapeCharacter;
|
||||||
|
|
||||||
|
this.repetitionDelimiterString = "" + repetitionDelimiter;
|
||||||
|
this.fieldDelimiterString = "" + fieldDelimiter;
|
||||||
|
this.componentDelimiterString = "" + componentDelimiter;
|
||||||
|
this.subComponentDelimiterString = "" + subComponentDelimiter;
|
||||||
|
this.escapeCharacterString = "" + escapeCharacter;
|
||||||
|
|
||||||
|
this.value = componentDelimiterString + repetitionDelimiter + escapeCharacter + subComponentDelimiter;
|
||||||
|
this.msh1 = new MSH1(this.fieldDelimiterString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String decode(final String s) {
|
||||||
|
return s.replace(repetitionEscape, repetitionDelimiterString)
|
||||||
|
.replace(fieldEscape, fieldDelimiterString)
|
||||||
|
.replace(componentEscape, componentDelimiterString)
|
||||||
|
.replace(subComponentEscape, subComponentDelimiterString)
|
||||||
|
.replace(escapeEscape, escapeCharacterString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode(final String s) {
|
||||||
|
return s.replace(escapeCharacterString, escapeEscape)
|
||||||
|
.replace(repetitionDelimiterString, repetitionEscape)
|
||||||
|
.replace(fieldDelimiterString, fieldEscape)
|
||||||
|
.replace(componentDelimiterString, componentEscape)
|
||||||
|
.replace(subComponentDelimiterString, subComponentEscape);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> splitSegment(final String s) {
|
||||||
|
return split(s, segmentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> splitRepetition(final String s) {
|
||||||
|
return split(s, repetitionDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> splitField(final String s) {
|
||||||
|
return split(s, fieldDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> splitComponent(final String s) {
|
||||||
|
return split(s, componentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> splitSubComponent(final String s) {
|
||||||
|
return split(s, subComponentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> split(final String s, final char ch) {
|
||||||
|
int off = 0;
|
||||||
|
int next = 0;
|
||||||
|
final List<String> list = new ArrayList<>();
|
||||||
|
while ((next = s.indexOf(ch, off)) != -1) {
|
||||||
|
list.add(s.substring(off, next));
|
||||||
|
off = next + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add remaining segment
|
||||||
|
list.add(s.substring(off, s.length()));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
sb.append(this.value);
|
||||||
|
sb.append(enc.fieldDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubComponent value(final String value) {
|
||||||
|
// do nothing
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final String s) {
|
||||||
|
return value.equals(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MSH1 extends Field {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private MSH1(final String fieldDelimiter) {
|
||||||
|
this.value = fieldDelimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubComponent value(final String value) {
|
||||||
|
// do nothing
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final String s) {
|
||||||
|
return value.equals(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
public class Field extends SubComponentContainer<Repetition> {
|
||||||
|
|
||||||
|
Field() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
Field(final String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Field(final String s, final Encoding enc) {
|
||||||
|
super(s, enc, enc.repetitionDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Repetition newSubComponent() {
|
||||||
|
return new Repetition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Repetition newSubComponent(final String s) {
|
||||||
|
return new Repetition(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Repetition newSubComponent(final String s, final Encoding enc) {
|
||||||
|
return new Repetition(s, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
super.encode(sb, enc, enc.repetitionDelimiter, enc.fieldDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepetitionCounter repetitionCounter() {
|
||||||
|
return new RepetitionCounter(this, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepetitionCounter repetitionCounter(final int startIndex) {
|
||||||
|
return new RepetitionCounter(this, startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition repetition(final int index) {
|
||||||
|
return super.subComponent1Based(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component component(final int repetitionIndex, final int componentIndex) {
|
||||||
|
return this.repetition(repetitionIndex).component(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component component(final int index) {
|
||||||
|
return this.repetition(1).component(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int repetitionIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.repetition(repetitionIndex).component(componentIndex).subComponent(subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.component(componentIndex).subComponent(subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
public RepetitionCounter rc() {
|
||||||
|
return this.repetitionCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepetitionCounter rc(final int startIndex) {
|
||||||
|
return this.repetitionCounter(startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition r(final int repetitionIndex) {
|
||||||
|
return this.repetition(repetitionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component c(final int repetitionIndex, final int componentIndex) {
|
||||||
|
return this.component(repetitionIndex, componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component c(final int componentIndex) {
|
||||||
|
return this.component(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent sc(final int repetitionIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.subComponent(repetitionIndex, componentIndex, subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent sc(final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.subComponent(componentIndex, subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString("Repetition");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
public class Line extends SubComponentContainer<Field> {
|
||||||
|
|
||||||
|
public Line(final String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Line(final String s, final Encoding enc) {
|
||||||
|
super(s, enc, enc.fieldDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Field newSubComponent() {
|
||||||
|
return new Field();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Field newSubComponent(final String s) {
|
||||||
|
return new Field(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Field newSubComponent(final String s, final Encoding enc) {
|
||||||
|
return new Field(s, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
super.encode(sb, enc, enc.fieldDelimiter, enc.segmentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field field(final int index) {
|
||||||
|
return super.subComponent0Based(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition repetition(final int fieldIndex, final int repetitionIndex) {
|
||||||
|
return this.field(fieldIndex).repetition(repetitionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component component(final int fieldIndex, final int repetitionIndex, final int componentIndex) {
|
||||||
|
return this.field(fieldIndex).repetition(repetitionIndex).component(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component component(final int fieldIndex, final int componentIndex) {
|
||||||
|
return this.field(fieldIndex).component(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int fieldIndex, final int repetitionIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.field(fieldIndex).repetition(repetitionIndex).component(componentIndex).subComponent(subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int fieldIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.field(fieldIndex).component(componentIndex).subComponent(subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
public Field f(final int index) {
|
||||||
|
return this.field(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition r(final int fieldIndex, final int repetitionIndex) {
|
||||||
|
return this.repetition(fieldIndex, repetitionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component c(final int fieldIndex, final int repetitionIndex, final int componentIndex) {
|
||||||
|
return this.component(fieldIndex, repetitionIndex, componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component c(final int fieldIndex, final int componentIndex) {
|
||||||
|
return this.component(fieldIndex, componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent sc(final int fieldIndex, final int repetitionIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.subComponent(fieldIndex, repetitionIndex, componentIndex, subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent sc(final int fieldIndex, final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.subComponent(fieldIndex, componentIndex, subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString("Line");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Message {
|
||||||
|
|
||||||
|
public static final Encoding DEFAULT_ENCODING = new Encoding('\r', '~', '|', '^', '&', '\\'); // http://healthstandards.com/blog/2006/11/02/hl7-escape-sequences/
|
||||||
|
public static final Encoding NEWLINE_ENCODING = new Encoding('\n', '~', '|', '^', '&', '\\');
|
||||||
|
|
||||||
|
private final List<Line> lines = new ArrayList<>();
|
||||||
|
|
||||||
|
public Message() {
|
||||||
|
line("MSH");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message(final String sendingApplication, final String sendingFacility, final String receivingApplication, final String receivingFacility, final String messageCode, final String messageTriggerEvent, final String messageControlId, final String processingId, final String version) {
|
||||||
|
final Line msh = line("MSH");
|
||||||
|
msh.field(3).value(sendingApplication);
|
||||||
|
msh.field(4).value(sendingFacility);
|
||||||
|
msh.field(5).value(receivingApplication);
|
||||||
|
msh.field(6).value(receivingFacility);
|
||||||
|
msh.field(7).date(Instant.now());
|
||||||
|
|
||||||
|
final Field messageType = msh.field(9);
|
||||||
|
messageType.component(1).value(messageCode);
|
||||||
|
messageType.component(2).value(messageTriggerEvent);
|
||||||
|
messageType.component(3).value(messageCode + "_" + messageTriggerEvent);
|
||||||
|
|
||||||
|
msh.field(10).value(messageControlId);
|
||||||
|
msh.field(11).value(processingId);
|
||||||
|
msh.field(12).value(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message(final String s) throws ParseException {
|
||||||
|
final int mshIdx = s.indexOf("MSH");
|
||||||
|
if(mshIdx == -1 || s.length() < (mshIdx + 8))
|
||||||
|
throw new ParseException("HL7 messages must start with an MSH segment", 0);
|
||||||
|
|
||||||
|
// detect segmentDelimiter
|
||||||
|
char segmentDelimiter = DEFAULT_ENCODING.segmentDelimiter;
|
||||||
|
final char fieldDelimiter = s.charAt(mshIdx + 3);
|
||||||
|
byte fieldDelimiterCount = 0;
|
||||||
|
// 11 fields in is the version, next non-number or . is segmentDelimiter
|
||||||
|
for(int i = mshIdx; i < s.length(); ++i) {
|
||||||
|
if(fieldDelimiterCount < 11) {
|
||||||
|
if(s.charAt(i) == fieldDelimiter)
|
||||||
|
++fieldDelimiterCount;
|
||||||
|
} else {
|
||||||
|
final char c = s.charAt(i);
|
||||||
|
if(c != '.' && !Character.isDigit(c)) {
|
||||||
|
segmentDelimiter = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Encoding enc = new Encoding(segmentDelimiter, s.charAt(mshIdx + 5), fieldDelimiter, s.charAt(mshIdx + 4), s.charAt(mshIdx + 7), s.charAt(mshIdx + 6));
|
||||||
|
for(final String line : enc.splitSegment("MSH" + fieldDelimiter + s.substring(mshIdx + 8)))
|
||||||
|
if(!line.isEmpty())
|
||||||
|
lines.add(new Line(line, enc));
|
||||||
|
// shift MSH one to account for brain-dead 1st field while setting encoding
|
||||||
|
final Line msh = this.lines.get(0);
|
||||||
|
msh.field(2); // expand array sufficiently
|
||||||
|
msh.subComponents.add(1, enc.msh1);
|
||||||
|
msh.subComponents.set(2, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode() {
|
||||||
|
return this.encode(DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode(final Encoding enc) {
|
||||||
|
// set encoding
|
||||||
|
final Line msh = this.lines.get(0);
|
||||||
|
msh.field(2); // expand array sufficiently
|
||||||
|
msh.subComponents.set(1, enc.msh1);
|
||||||
|
msh.subComponents.set(2, enc);
|
||||||
|
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for(final Line line : lines)
|
||||||
|
line.encode(sb, enc);
|
||||||
|
if(!lines.isEmpty()){
|
||||||
|
int index = 1;
|
||||||
|
while (index > 0 && sb.charAt(index = sb.length() - 1) == enc.segmentDelimiter)
|
||||||
|
sb.setLength(index);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line optionalLine(final String type) {
|
||||||
|
for(final Line line : lines)
|
||||||
|
if(line.field(0).equals(type))
|
||||||
|
return line;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line line(final String type) {
|
||||||
|
Line line = optionalLine(type);
|
||||||
|
if(line == null)
|
||||||
|
lines.add(line = new Line(type));
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line line(final int index) {
|
||||||
|
return lines.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Line> getLines() {
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Line> lines(final String type) {
|
||||||
|
return lines.stream().filter(l -> l.field(0).equals(type)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line add(final String line) {
|
||||||
|
final Line ret = new Line(line);
|
||||||
|
lines.add(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message add(final Line line) {
|
||||||
|
lines.add(line);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message writeAndRead(final Socket sock, final Encoding enc) throws IOException, ParseException {
|
||||||
|
return this.writeAndRead(sock.getOutputStream(), sock.getInputStream(), enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message writeAndRead(final OutputStream os, final InputStream is, final Encoding enc) throws IOException, ParseException {
|
||||||
|
this.writeTo(os, enc);
|
||||||
|
os.flush();
|
||||||
|
return readFrom(is, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(final OutputStream os, final Encoding enc) throws IOException {
|
||||||
|
os.write(enc.verticalTab);
|
||||||
|
// todo: this can be made dramatically faster by writing to this directly instead of a StringBuilder
|
||||||
|
os.write(this.encode(enc).getBytes(StandardCharsets.US_ASCII));
|
||||||
|
os.write(enc.fileSeperator);
|
||||||
|
os.write(enc.segmentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message readFrom(final InputStream is, final Encoding enc) throws IOException, ParseException {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = -1; (i = is.read()) != -1; ) {
|
||||||
|
//System.out.println("i: "+i);
|
||||||
|
final char c = (char) i;
|
||||||
|
//System.out.println("c: "+c);
|
||||||
|
if (c == enc.fileSeperator) { // end of line/message
|
||||||
|
// next char should be segmentDelimiter
|
||||||
|
i = is.read();
|
||||||
|
if (((char) i) != enc.segmentDelimiter)
|
||||||
|
throw new ParseException("HL7 messages have a segmentDelimiter directly following a fileSeperator", sb.length());
|
||||||
|
return new Message(sb.toString());
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; // no complete message received
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message writeAndRead(final Socket sock) throws IOException, ParseException {
|
||||||
|
return this.writeAndRead(sock, DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message writeAndRead(final OutputStream os, final InputStream is) throws IOException, ParseException {
|
||||||
|
return this.writeAndRead(os, is, DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(final OutputStream os) throws IOException {
|
||||||
|
this.writeTo(os, DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message readFrom(final InputStream is) throws IOException, ParseException {
|
||||||
|
return readFrom(is, DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Message" + lines;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
public class Repetition extends SubComponentContainer<Component> {
|
||||||
|
|
||||||
|
Repetition() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
Repetition(final String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Repetition(final String s, final Encoding enc) {
|
||||||
|
super(s, enc, enc.componentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Component newSubComponent() {
|
||||||
|
return new Component();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Component newSubComponent(final String s) {
|
||||||
|
return new Component(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Component newSubComponent(final String s, final Encoding enc) {
|
||||||
|
return new Component(s, enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
super.encode(sb, enc, enc.componentDelimiter, enc.repetitionDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component component(final int index) {
|
||||||
|
return super.subComponent1Based(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent subComponent(final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.component(componentIndex).subComponent(subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
public Component c(final int componentIndex) {
|
||||||
|
return this.component(componentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubComponent sc(final int componentIndex, final int subComponentIndex) {
|
||||||
|
return this.subComponent(componentIndex, subComponentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString("Component");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
public class RepetitionCounter {
|
||||||
|
|
||||||
|
private final Field field;
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
RepetitionCounter(final Field field, final int index) {
|
||||||
|
this.field = field;
|
||||||
|
this.index = index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition nextRepetition() {
|
||||||
|
return field.r(++index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition currentRepetition() {
|
||||||
|
return field.r(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
public Repetition nr() {
|
||||||
|
return nextRepetition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Repetition cr() {
|
||||||
|
return currentRepetition();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.time.format.ResolverStyle;
|
||||||
|
import java.time.format.SignStyle;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static java.time.temporal.ChronoField.*;
|
||||||
|
|
||||||
|
public interface SubComponent {
|
||||||
|
|
||||||
|
DateTimeFormatter LOCAL_DATE = new DateTimeFormatterBuilder()
|
||||||
|
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
||||||
|
.appendValue(MONTH_OF_YEAR, 2)
|
||||||
|
.appendValue(DAY_OF_MONTH, 2)
|
||||||
|
.parseStrict()
|
||||||
|
.toFormatter(Locale.US)
|
||||||
|
.withResolverStyle(ResolverStyle.STRICT);
|
||||||
|
|
||||||
|
DateTimeFormatter LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
|
||||||
|
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
||||||
|
.appendValue(MONTH_OF_YEAR, 2)
|
||||||
|
.appendValue(DAY_OF_MONTH, 2)
|
||||||
|
.appendValue(HOUR_OF_DAY, 2)
|
||||||
|
.appendValue(MINUTE_OF_HOUR, 2)
|
||||||
|
.parseStrict()
|
||||||
|
.toFormatter(Locale.US)
|
||||||
|
.withResolverStyle(ResolverStyle.STRICT);
|
||||||
|
|
||||||
|
DateTimeFormatter INSTANT = new DateTimeFormatterBuilder()
|
||||||
|
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
||||||
|
.appendValue(MONTH_OF_YEAR, 2)
|
||||||
|
.appendValue(DAY_OF_MONTH, 2)
|
||||||
|
.appendValue(HOUR_OF_DAY, 2)
|
||||||
|
.appendValue(MINUTE_OF_HOUR, 2)
|
||||||
|
.appendValue(SECOND_OF_MINUTE, 2)
|
||||||
|
.appendLiteral('.')
|
||||||
|
.appendValue(MILLI_OF_SECOND, 3)
|
||||||
|
.appendOffset("+HHMM", "0000")
|
||||||
|
.parseStrict()
|
||||||
|
.toFormatter(Locale.US)
|
||||||
|
.withZone(ZoneId.systemDefault())
|
||||||
|
.withResolverStyle(ResolverStyle.STRICT);
|
||||||
|
|
||||||
|
SubComponent value(final String value);
|
||||||
|
|
||||||
|
String value();
|
||||||
|
|
||||||
|
boolean equals(final String s);
|
||||||
|
|
||||||
|
void encode(final StringBuilder sb, final Encoding enc);
|
||||||
|
|
||||||
|
default boolean isEmpty() {
|
||||||
|
return this.equals("");
|
||||||
|
}
|
||||||
|
|
||||||
|
default void date(final LocalDate date) {
|
||||||
|
this.value(LOCAL_DATE.format(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
default void date(final LocalDateTime date) {
|
||||||
|
this.value(LOCAL_DATE_TIME.format(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
default void date(final Instant date) {
|
||||||
|
this.value(INSTANT.format(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorter aliases
|
||||||
|
|
||||||
|
default SubComponent v(final String value) {
|
||||||
|
return this.value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
default String v() {
|
||||||
|
return this.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
default void d(final LocalDate date) {
|
||||||
|
this.date(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void d(final LocalDateTime date) {
|
||||||
|
this.date(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void d(final Instant date) {
|
||||||
|
this.date(date);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
abstract class SubComponentContainer<T extends SubComponent> implements SubComponent {
|
||||||
|
|
||||||
|
protected final List<T> subComponents = new ArrayList<>();
|
||||||
|
|
||||||
|
protected SubComponentContainer() {
|
||||||
|
subComponents.add(newSubComponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SubComponentContainer(final String s) {
|
||||||
|
subComponents.add(newSubComponent(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SubComponentContainer(final String s, final Encoding enc, final char thisDelimiter) {
|
||||||
|
for(final String line : enc.split(s, thisDelimiter))
|
||||||
|
subComponents.add(newSubComponent(line, enc));
|
||||||
|
if(subComponents.isEmpty())
|
||||||
|
subComponents.add(newSubComponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract T newSubComponent();
|
||||||
|
abstract T newSubComponent(final String s);
|
||||||
|
abstract T newSubComponent(final String s, final Encoding enc);
|
||||||
|
|
||||||
|
protected final void encode(final StringBuilder sb, final Encoding enc, final char thisDelimiter, final char parentDelimiter) {
|
||||||
|
for(final SubComponent e : subComponents)
|
||||||
|
e.encode(sb, enc);
|
||||||
|
if(!subComponents.isEmpty()){
|
||||||
|
int index = 1, count = -1;
|
||||||
|
while (++count < subComponents.size() && index > 0 && sb.charAt(index = sb.length() - 1) == thisDelimiter)
|
||||||
|
sb.setLength(index);
|
||||||
|
}
|
||||||
|
sb.append(parentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T subComponent0Based(final int index) {
|
||||||
|
while(subComponents.size() <= index)
|
||||||
|
subComponents.add(newSubComponent());
|
||||||
|
return subComponents.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T subComponent1Based(final int index) {
|
||||||
|
while(subComponents.size() < index)
|
||||||
|
subComponents.add(newSubComponent());
|
||||||
|
return subComponents.get(index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubComponent value(final String value) {
|
||||||
|
if(subComponents.size() == 1) {
|
||||||
|
subComponents.get(0).value(value);
|
||||||
|
} else {
|
||||||
|
subComponents.clear();
|
||||||
|
subComponents.add(newSubComponent(value));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String value() {
|
||||||
|
// todo: this isn't ALWAYS correct, it just returns the first, ignoring any other field/repetition/component/subcomponent/whatever
|
||||||
|
return subComponents.isEmpty() ? "" : subComponents.get(0).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final String s) {
|
||||||
|
// more complicated than you'd think
|
||||||
|
if("".equals(s)) {
|
||||||
|
// special case for empty string
|
||||||
|
if(subComponents.isEmpty())
|
||||||
|
return true;
|
||||||
|
// otherwise every one needs to be empty
|
||||||
|
for(final SubComponent sc : subComponents)
|
||||||
|
if(!sc.isEmpty())
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if(subComponents.isEmpty())
|
||||||
|
return false;
|
||||||
|
boolean first = true;
|
||||||
|
// first has to match, and every OTHER one needs to be empty now...
|
||||||
|
for(final SubComponent sc : subComponents) {
|
||||||
|
if (!(first ? sc.equals(s) : sc.isEmpty()))
|
||||||
|
return false;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String toString(final String name) {
|
||||||
|
return subComponents.size() == 1 ? subComponents.get(0).toString() : name + subComponents;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Travis Burtrum.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of the
|
||||||
|
* GNU General Public License (the "GPL"), in which case the provisions of the GPL are
|
||||||
|
* applicable instead of those above. If you wish to allow use of your version of this
|
||||||
|
* file only under the terms of the GPL and not to allow others to use your version
|
||||||
|
* of this file under the MPL, indicate your decision by deleting the provisions above
|
||||||
|
* and replace them with the notice and other provisions required by the GPL License.
|
||||||
|
* If you do not delete the provisions above, a recipient may use your version of
|
||||||
|
* this file under either the MPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.moparisthebest.hl7;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
class SubComponentImpl implements SubComponent {
|
||||||
|
|
||||||
|
protected String value;
|
||||||
|
|
||||||
|
SubComponentImpl() {
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
SubComponentImpl(final String value) {
|
||||||
|
value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubComponentImpl(final String s, final Encoding enc) {
|
||||||
|
this.value = enc.decode(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(final StringBuilder sb, final Encoding enc) {
|
||||||
|
sb.append(enc.encode(this.value));
|
||||||
|
sb.append(enc.subComponentDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
String encode(final Encoding enc) {
|
||||||
|
return enc.encode(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubComponent value(final String value) {
|
||||||
|
this.value = value == null ? "" : value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final String s) {
|
||||||
|
return Objects.equals(value, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue