NIFI-506: Initial import of HL7 work

This commit is contained in:
Mark Payne 2015-04-09 17:54:33 -04:00
parent e8fde85914
commit 45416dc66b
66 changed files with 3862 additions and 0 deletions

View File

@ -0,0 +1,3 @@
/target/
/target/
/target/

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-commons</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>nifi-hl7-query-language</artifactId>
<packaging>jar</packaging>
<name>NiFi Health Level 7 (HL7) Query Language</name>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>antlr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.5.2</version>
</dependency>
<!-- HAPI to parse v2 messages -->
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-base</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v21</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v22</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v23</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v231</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v24</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v25</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v251</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v26</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,156 @@
lexer grammar HL7QueryLexer;
@header {
package org.apache.nifi.hl7.query.antlr;
import org.apache.nifi.hl7.query.exception.HL7QueryParsingException;
}
@rulecatch {
catch(final Exception e) {
throw new HL7QueryParsingException(e);
}
}
@members {
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
final StringBuilder sb = new StringBuilder();
if ( e.token == null ) {
sb.append("Unrecognized token ");
} else {
sb.append("Unexpected token '").append(e.token.getText()).append("' ");
}
sb.append("at line ").append(e.line);
if ( e.approximateLineInfo ) {
sb.append(" (approximately)");
}
sb.append(", column ").append(e.charPositionInLine);
sb.append(". Query: ").append(e.input.toString());
throw new HL7QueryParsingException(sb.toString());
}
public void recover(RecognitionException e) {
final StringBuilder sb = new StringBuilder();
if ( e.token == null ) {
sb.append("Unrecognized token ");
} else {
sb.append("Unexpected token '").append(e.token.getText()).append("' ");
}
sb.append("at line ").append(e.line);
if ( e.approximateLineInfo ) {
sb.append(" (approximately)");
}
sb.append(", column ").append(e.charPositionInLine);
sb.append(". Query: ").append(e.input.toString());
throw new HL7QueryParsingException(sb.toString());
}
}
// PUNCTUATION & SPECIAL CHARACTERS
WHITESPACE : (' '|'\t'|'\n'|'\r')+ { $channel = HIDDEN; };
COMMENT : '#' ( ~('\n') )* '\n' { $channel = HIDDEN; };
LPAREN : '(';
RPAREN : ')';
LBRACE : '{';
RBRACE : '}';
COLON : ':';
COMMA : ',';
DOT : '.';
SEMICOLON : ';';
// OPERATORS
EQUALS : '=';
NOT_EQUALS : '!=';
GT : '>';
GE : '>=';
LT : '<';
LE : '<=';
REGEX : 'MATCHES REGEX';
LIKE : 'LIKE';
IS_NULL : 'IS NULL';
NOT_NULL : 'NOT NULL';
// KEYWORDS
AND : 'AND';
OR : 'OR';
NOT : 'NOT';
TRUE : 'true';
FALSE : 'false';
SELECT : 'select' | 'SELECT';
DECLARE : 'declare' | 'DECLARE';
OPTIONAL : 'optional' | 'OPTIONAL';
REQUIRED : 'required' | 'REQUIRED';
AS : 'as' | 'AS';
WHERE : 'where' | 'WHERE';
MESSAGE : 'MESSAGE' | 'message';
SEGMENT : 'SEGMENT' | 'segment';
SEGMENT_NAME : LETTER ALPHA_NUMERIC ALPHA_NUMERIC;
NUMBER : ('0'..'9')+;
fragment LETTER : 'A'..'Z';
fragment ALPHA_NUMERIC : 'A'..'Z' | '0'..'9';
// STRINGS
STRING_LITERAL
@init{StringBuilder lBuf = new StringBuilder();}
:
(
'"'
(
escaped=ESC {lBuf.append(getText());} |
normal = ~( '"' | '\\' | '\n' | '\r' | '\t' ) { lBuf.appendCodePoint(normal);}
)*
'"'
)
{
setText(lBuf.toString());
}
|
(
'\''
(
escaped=ESC {lBuf.append(getText());} |
normal = ~( '\'' | '\\' | '\n' | '\r' | '\t' ) { lBuf.appendCodePoint(normal);}
)*
'\''
)
{
setText(lBuf.toString());
}
;
fragment
ESC
: '\\'
(
'"' { setText("\""); }
| '\'' { setText("\'"); }
| 'r' { setText("\r"); }
| 'n' { setText("\n"); }
| 't' { setText("\t"); }
| '\\' { setText("\\\\"); }
| nextChar = ~('"' | '\'' | 'r' | 'n' | 't' | '\\')
{
StringBuilder lBuf = new StringBuilder(); lBuf.append("\\\\").appendCodePoint(nextChar); setText(lBuf.toString());
}
)
;
IDENTIFIER : (
~('$' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ':' | ';' | '/' | '*' | '\'' | ' ' | '\t' | '\r' | '\n' | '0'..'9' | '.')
~('$' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ':' | ';' | '/' | '*' | '\'' | ' ' | '\t' | '\r' | '\n' | '.')*
);

View File

@ -0,0 +1,91 @@
parser grammar HL7QueryParser;
options {
output=AST;
tokenVocab=HL7QueryLexer;
}
tokens {
QUERY;
DECLARATION;
}
@header {
package org.apache.nifi.hl7.query.antlr;
import org.apache.nifi.hl7.query.exception.HL7QueryParsingException;
}
@members {
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
final StringBuilder sb = new StringBuilder();
if ( e.token == null ) {
sb.append("Unrecognized token ");
} else {
sb.append("Unexpected token '").append(e.token.getText()).append("' ");
}
sb.append("at line ").append(e.line);
if ( e.approximateLineInfo ) {
sb.append(" (approximately)");
}
sb.append(", column ").append(e.charPositionInLine);
sb.append(". Query: ").append(e.input.toString());
throw new HL7QueryParsingException(sb.toString());
}
public void recover(final RecognitionException e) {
final StringBuilder sb = new StringBuilder();
if ( e.token == null ) {
sb.append("Unrecognized token ");
} else {
sb.append("Unexpected token '").append(e.token.getText()).append("' ");
}
sb.append("at line ").append(e.line);
if ( e.approximateLineInfo ) {
sb.append(" (approximately)");
}
sb.append(", column ").append(e.charPositionInLine);
sb.append(". Query: ").append(e.input.toString());
throw new HL7QueryParsingException(sb.toString());
}
}
declareClause : DECLARE^ declaration (COMMA! declaration)*;
requiredOrOptional : REQUIRED | OPTIONAL;
declaration : IDENTIFIER AS requiredOrOptional SEGMENT_NAME ->
^(DECLARATION IDENTIFIER requiredOrOptional SEGMENT_NAME);
selectClause : SELECT^ selectableClause;
selectableClause : selectable (COMMA! selectable)*;
selectable : (MESSAGE | ref | field)^ (AS! IDENTIFIER^)?;
whereClause : WHERE^ conditions;
conditions : condition ((AND^ | OR^) condition)*;
condition : NOT^ condition | LPAREN! conditions RPAREN! | evaluation;
evaluation : expression
(
unaryOperator^
| (binaryOperator^ expression)
);
expression : (LPAREN! expr RPAREN!) | expr;
expr : ref | field | STRING_LITERAL | NUMBER;
unaryOperator : IS_NULL | NOT_NULL;
binaryOperator : EQUALS | NOT_EQUALS | LT | GT | LE | GE;
ref : (SEGMENT_NAME | IDENTIFIER);
field : ref DOT^ NUMBER
(DOT^ NUMBER (DOT^ NUMBER (DOT^ NUMBER)?)?)?;
query : declareClause? selectClause whereClause? EOF ->
^(QUERY declareClause? selectClause whereClause?);

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.hapi;
import java.util.Collections;
import java.util.List;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.model.HL7Field;
public class EmptyField implements HL7Field {
@Override
public String getValue() {
return null;
}
@Override
public List<HL7Component> getComponents() {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.hapi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.model.HL7Field;
import ca.uhn.hl7v2.model.Composite;
import ca.uhn.hl7v2.model.ExtraComponents;
import ca.uhn.hl7v2.model.Primitive;
import ca.uhn.hl7v2.model.Type;
import ca.uhn.hl7v2.model.Varies;
import ca.uhn.hl7v2.parser.EncodingCharacters;
import ca.uhn.hl7v2.parser.PipeParser;
public class HapiField implements HL7Field, HL7Component {
private final String value;
private final List<HL7Component> components;
public HapiField(final Type type) {
this.value = PipeParser.encode(type, EncodingCharacters.defaultInstance());
final List<HL7Component> componentList = new ArrayList<>();
if ( type instanceof Composite ) {
final Composite composite = (Composite) type;
for ( final Type component : composite.getComponents() ) {
componentList.add(new HapiField(component));
}
}
final ExtraComponents extra = type.getExtraComponents();
if ( extra != null && extra.numComponents() > 0 ) {
final String singleFieldValue;
if ( type instanceof Primitive ) {
singleFieldValue = ((Primitive) type).getValue();
} else {
singleFieldValue = this.value;
}
componentList.add(new SingleValueField(singleFieldValue));
for (int i=0; i < extra.numComponents(); i++) {
final Varies varies = extra.getComponent(i);
componentList.add(new HapiField(varies));
}
}
this.components = Collections.unmodifiableList(componentList);
}
@Override
public String getValue() {
return value;
}
@Override
public List<HL7Component> getComponents() {
return components;
}
@Override
public String toString() {
return value;
}
}

View File

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.hapi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.model.HL7Segment;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Group;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.model.Structure;
public class HapiMessage implements HL7Message {
private final Message message;
private final List<HL7Segment> allSegments;
private final Map<String, List<HL7Segment>> segmentMap;
public HapiMessage(final Message message) throws HL7Exception {
this.message = message;
allSegments = new ArrayList<>();
populateSegments(message, allSegments);
segmentMap = new HashMap<>();
for ( final HL7Segment segment : allSegments ) {
final String segmentName = segment.getName();
List<HL7Segment> segmentList = segmentMap.get(segmentName);
if ( segmentList == null ) {
segmentList = new ArrayList<>();
segmentMap.put(segmentName, segmentList);
}
segmentList.add(segment);
}
}
private void populateSegments(final Group group, final List<HL7Segment> segments) throws HL7Exception {
for ( final String structureName : group.getNames() ) {
final Structure[] structures = group.getAll(structureName);
if ( group.isGroup(structureName) ) {
for ( final Structure structure : structures ) {
populateSegments((Group) structure, segments);
}
} else {
for ( final Structure structure : structures ) {
final Segment segment = (Segment) structure;
final HapiSegment hapiSegment = new HapiSegment(segment);
segments.add(hapiSegment);
}
}
}
}
@Override
public List<HL7Segment> getSegments() {
return Collections.unmodifiableList(allSegments);
}
@Override
public List<HL7Segment> getSegments(final String segmentType) {
final List<HL7Segment> segments = segmentMap.get(segmentType);
if ( segments == null ) {
return Collections.emptyList();
}
return Collections.unmodifiableList(segments);
}
@Override
public String toString() {
return message.toString();
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.hapi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.nifi.hl7.model.HL7Field;
import org.apache.nifi.hl7.model.HL7Segment;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.model.Type;
public class HapiSegment implements HL7Segment {
private final Segment segment;
private final List<HL7Field> fields;
public HapiSegment(final Segment segment) throws HL7Exception {
this.segment = segment;
final List<HL7Field> fieldList = new ArrayList<>();
for (int i=1; i <= segment.numFields(); i++) {
final Type[] types = segment.getField(i);
if ( types == null || types.length == 0 ) {
fieldList.add(new EmptyField());
continue;
}
for ( final Type type : types ) {
fieldList.add(new HapiField(type));
}
}
this.fields = Collections.unmodifiableList(fieldList);
}
@Override
public String getName() {
return segment.getName();
}
@Override
public List<HL7Field> getFields() {
return fields;
}
@Override
public String toString() {
return segment.toString();
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.hapi;
import java.util.Collections;
import java.util.List;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.model.HL7Field;
public class SingleValueField implements HL7Field {
private final String value;
public SingleValueField(final String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
@Override
public List<HL7Component> getComponents() {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.io;
import java.io.IOException;
import org.apache.nifi.hl7.model.HL7Message;
public interface HL7Reader {
HL7Message nextMessage() throws IOException;
}

View File

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.io.exception;
import java.io.IOException;
public class InvalidHL7Exception extends IOException {
private static final long serialVersionUID = -5675416667224562441L;
public InvalidHL7Exception() {
super();
}
public InvalidHL7Exception(String message, Throwable cause) {
super(message, cause);
}
public InvalidHL7Exception(String message) {
super(message);
}
public InvalidHL7Exception(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.model;
import java.util.List;
public interface HL7Component {
String getValue();
List<HL7Component> getComponents();
}

View File

@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.model;
public interface HL7Field extends HL7Component {
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.model;
import java.util.List;
public interface HL7Message {
List<HL7Segment> getSegments();
List<HL7Segment> getSegments(String segmentType);
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.model;
import java.util.List;
public interface HL7Segment {
String getName();
List<HL7Field> getFields();
}

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import org.apache.nifi.hl7.model.HL7Message;
public interface Declaration {
String getAlias();
boolean isRequired();
Object getDeclaredValue(HL7Message message);
}

View File

@ -0,0 +1,412 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import static org.apache.nifi.hl7.query.antlr.HL7QueryParser.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.Tree;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
import org.apache.nifi.hl7.query.evaluator.IntegerEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.EqualsEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.GreaterThanEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.GreaterThanOrEqualEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.IsNullEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.LessThanEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.LessThanOrEqualEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.NotEqualsEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.NotEvaluator;
import org.apache.nifi.hl7.query.evaluator.comparison.NotNullEvaluator;
import org.apache.nifi.hl7.query.evaluator.literal.IntegerLiteralEvaluator;
import org.apache.nifi.hl7.query.evaluator.literal.StringLiteralEvaluator;
import org.apache.nifi.hl7.query.evaluator.logic.AndEvaluator;
import org.apache.nifi.hl7.query.evaluator.logic.OrEvaluator;
import org.apache.nifi.hl7.query.evaluator.message.DeclaredReferenceEvaluator;
import org.apache.nifi.hl7.query.evaluator.message.DotEvaluator;
import org.apache.nifi.hl7.query.evaluator.message.MessageEvaluator;
import org.apache.nifi.hl7.query.evaluator.message.SegmentEvaluator;
import org.apache.nifi.hl7.query.exception.HL7QueryParsingException;
import org.apache.nifi.hl7.query.result.MissedResult;
import org.apache.nifi.hl7.query.result.StandardQueryResult;
import org.apache.nifi.hl7.query.antlr.HL7QueryLexer;
import org.apache.nifi.hl7.query.antlr.HL7QueryParser;
public class HL7Query {
private final Tree tree;
private final String query;
private final Set<Declaration> declarations = new HashSet<>();
private final List<Selection> selections;
private final BooleanEvaluator whereEvaluator;
private HL7Query(final Tree tree, final String query) {
this.tree = tree;
this.query = query;
List<Selection> select = null;
BooleanEvaluator where = null;
for (int i=0; i < tree.getChildCount(); i++) {
final Tree child = tree.getChild(i);
switch (child.getType()) {
case DECLARE:
processDeclare(child);
break;
case SELECT:
select = processSelect(child);
break;
case WHERE:
where = processWhere(child);
break;
default:
throw new HL7QueryParsingException("Found unexpected clause at root level: " + tree.getText());
}
}
this.whereEvaluator = where;
this.selections = select;
}
private void processDeclare(final Tree declare) {
for (int i=0; i < declare.getChildCount(); i++) {
final Tree declarationTree = declare.getChild(i);
final String identifier = declarationTree.getChild(0).getText();
final Tree requiredOrOptionalTree = declarationTree.getChild(1);
final boolean required = requiredOrOptionalTree.getType() == REQUIRED;
final String segmentName = declarationTree.getChild(2).getText();
final Declaration declaration = new Declaration() {
@Override
public String getAlias() {
return identifier;
}
@Override
public boolean isRequired() {
return required;
}
@Override
public Object getDeclaredValue(final HL7Message message) {
if ( message == null ) {
return null;
}
return message.getSegments(segmentName);
}
};
declarations.add(declaration);
}
}
private List<Selection> processSelect(final Tree select) {
final List<Selection> selections = new ArrayList<>();
for (int i=0; i < select.getChildCount(); i++) {
final Tree selectable = select.getChild(i);
final String alias = getSelectedName(selectable);
final Evaluator<?> selectionEvaluator = buildReferenceEvaluator(selectable);
final Selection selection = new Selection(selectionEvaluator, alias);
selections.add(selection);
}
return selections;
}
private String getSelectedName(final Tree selectable) {
if ( selectable.getChildCount() == 0 ) {
return selectable.getText();
} else if (selectable.getType() == DOT ) {
return getSelectedName(selectable.getChild(0)) + "." + getSelectedName(selectable.getChild(1));
} else {
return selectable.getChild(selectable.getChildCount() - 1).getText();
}
}
private BooleanEvaluator processWhere(final Tree where) {
return buildBooleanEvaluator(where.getChild(0));
}
private Evaluator<?> buildReferenceEvaluator(final Tree tree) {
switch (tree.getType()) {
case MESSAGE:
return new MessageEvaluator();
case SEGMENT_NAME:
return new SegmentEvaluator(new StringLiteralEvaluator(tree.getText()));
case IDENTIFIER:
return new DeclaredReferenceEvaluator(new StringLiteralEvaluator(tree.getText()));
case DOT:
final Tree firstChild = tree.getChild(0);
final Tree secondChild = tree.getChild(1);
return new DotEvaluator(buildReferenceEvaluator(firstChild), buildIntegerEvaluator(secondChild));
case STRING_LITERAL:
return new StringLiteralEvaluator(tree.getText());
case NUMBER:
return new IntegerLiteralEvaluator(Integer.parseInt(tree.getText()));
default:
throw new HL7QueryParsingException("Failed to build evaluator for " + tree.getText());
}
}
private IntegerEvaluator buildIntegerEvaluator(final Tree tree) {
switch (tree.getType()) {
case NUMBER:
return new IntegerLiteralEvaluator(Integer.parseInt(tree.getText()));
default:
throw new HL7QueryParsingException("Failed to build Integer Evaluator for " + tree.getText());
}
}
private BooleanEvaluator buildBooleanEvaluator(final Tree tree) {
// TODO: add Date comparisons
// LT/GT/GE/GE should allow for dates based on Field's Type
// BETWEEN
// DATE('2015/01/01')
// DATE('2015/01/01 12:00:00')
// DATE('24 HOURS AGO')
// DATE('YESTERDAY')
switch (tree.getType()) {
case EQUALS:
return new EqualsEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case NOT_EQUALS:
return new NotEqualsEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case GT:
return new GreaterThanEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case LT:
return new LessThanEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case GE:
return new GreaterThanOrEqualEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case LE:
return new LessThanOrEqualEvaluator(buildReferenceEvaluator(tree.getChild(0)), buildReferenceEvaluator(tree.getChild(1)));
case NOT:
return new NotEvaluator(buildBooleanEvaluator(tree.getChild(0)));
case AND:
return new AndEvaluator(buildBooleanEvaluator(tree.getChild(0)), buildBooleanEvaluator(tree.getChild(1)));
case OR:
return new OrEvaluator(buildBooleanEvaluator(tree.getChild(0)), buildBooleanEvaluator(tree.getChild(1)));
case IS_NULL:
return new IsNullEvaluator(buildReferenceEvaluator(tree.getChild(0)));
case NOT_NULL:
return new NotNullEvaluator(buildReferenceEvaluator(tree.getChild(0)));
default:
throw new HL7QueryParsingException("Cannot build boolean evaluator for '" + tree.getText() + "'");
}
}
Tree getTree() {
return tree;
}
public String getQuery() {
return query;
}
@Override
public String toString() {
return "HL7Query[" + query + "]";
}
public static HL7Query compile(final String query) {
try {
final CommonTokenStream lexerTokenStream = createTokenStream(query);
final HL7QueryParser parser = new HL7QueryParser(lexerTokenStream);
final Tree tree = (Tree) parser.query().getTree();
return new HL7Query(tree, query);
} catch (final HL7QueryParsingException e) {
throw e;
} catch (final Exception e) {
throw new HL7QueryParsingException(e);
}
}
private static CommonTokenStream createTokenStream(final String expression) throws HL7QueryParsingException {
final CharStream input = new ANTLRStringStream(expression);
final HL7QueryLexer lexer = new HL7QueryLexer(input);
return new CommonTokenStream(lexer);
}
public List<Class<?>> getReturnTypes() {
final List<Class<?>> returnTypes = new ArrayList<>();
for ( final Selection selection : selections ) {
returnTypes.add( selection.getEvaluator().getType() );
}
return returnTypes;
}
@SuppressWarnings("unchecked")
public QueryResult evaluate(final HL7Message message) {
int totalIterations = 1;
final LinkedHashMap<String, List<Object>> possibleValueMap = new LinkedHashMap<>();
for ( final Declaration declaration : declarations ) {
final Object value = declaration.getDeclaredValue(message);
if ( value == null && declaration.isRequired() ) {
return new MissedResult(selections);
}
final List<Object> possibleValues;
if ( value instanceof List ) {
possibleValues = (List<Object>) value;
} else if ( value instanceof Collection ) {
possibleValues = new ArrayList<Object>((Collection<Object>) value);
} else {
possibleValues = new ArrayList<>(1);
possibleValues.add(value);
}
if ( possibleValues.isEmpty() ) {
return new MissedResult(selections);
}
possibleValueMap.put(declaration.getAlias(), possibleValues);
totalIterations *= possibleValues.size();
}
final Set<Map<String, Object>> resultSet = new HashSet<>();
for (int i=0; i < totalIterations; i++) {
final Map<String, Object> aliasValues = assignAliases(possibleValueMap, i);
aliasValues.put(Evaluator.MESSAGE_KEY, message);
if (whereEvaluator == null || Boolean.TRUE.equals(whereEvaluator.evaluate(aliasValues))) {
final Map<String, Object> resultMap = new HashMap<>();
for ( final Selection selection : selections ) {
final Object value = selection.getEvaluator().evaluate(aliasValues);
resultMap.put(selection.getName(), value);
}
resultSet.add(resultMap);
}
}
// for ( final Declaration declaration : declarations ) {
// final Object value = declaration.getDeclaredValue(message);
// if ( value == null && declaration.isRequired() ) {
// return new MissedResult(selections);
// }
// objectMap.put(declaration.getAlias(), value);
// }
//
// if (whereEvaluator == null || Boolean.TRUE.equals(whereEvaluator.evaluate(objectMap))) {
// for ( final Selection selection : selections ) {
// final Object value = selection.getEvaluator().evaluate(objectMap);
// resultMap.put(selection.getName(), value);
// }
// } else {
// return new MissedResult(selections);
// }
return new StandardQueryResult(selections, resultSet);
}
// assigns one of the possible values to each alias, based on which iteration this is.
// require LinkedHashMap just to be very clear and explicit that the order of the Map MUST be guaranteed
// between multiple invocations of this method.
// package protected for testing visibility
// static Map<String, Object> assignAliases(final LinkedHashMap<String, List<Object>> possibleValues, final int iteration) {
// final Map<String, Object> aliasMap = new HashMap<>();
//
// int aliasIndex = possibleValues.size() - 1;
// for ( final Map.Entry<String, List<Object>> entry : possibleValues.entrySet() ) {
// final String alias = entry.getKey();
// final List<Object> validValues = entry.getValue();
//
// final int validValueIndex;
// if (aliasIndex > 0) {
// validValueIndex = iteration / aliasIndex;
// } else {
// validValueIndex = iteration;
// }
//
// final Object obj = validValues.get(validValueIndex % validValues.size());
// aliasMap.put(alias, obj);
//
// aliasIndex--;
// }
//
// return aliasMap;
// }
//
static Map<String, Object> assignAliases(final LinkedHashMap<String, List<Object>> possibleValues, final int iteration) {
final Map<String, Object> aliasMap = new HashMap<>();
int divisor = 1;
for ( final Map.Entry<String, List<Object>> entry : possibleValues.entrySet() ) {
final String alias = entry.getKey();
final List<Object> validValues = entry.getValue();
final int idx = (iteration / divisor) % validValues.size();
final Object obj = validValues.get(idx);
aliasMap.put(alias, obj);
divisor *= validValues.size();
}
return aliasMap;
}
public String toTreeString() {
final StringBuilder sb = new StringBuilder();
toTreeString(tree, sb, 0);
return sb.toString();
}
private void toTreeString(final Tree tree, final StringBuilder sb, final int indentLevel) {
final String nodeName = tree.getText();
for (int i=0; i < indentLevel; i++) {
sb.append(" ");
}
sb.append(nodeName);
sb.append("\n");
for (int i=0; i < tree.getChildCount(); i++) {
final Tree child = tree.getChild(i);
toTreeString(child, sb, indentLevel + 2);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import java.util.List;
public interface QueryResult {
boolean isMatch();
List<String> getLabels();
int getHitCount();
ResultHit nextHit();
}

View File

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import java.util.Map;
public interface ResultHit {
Object getValue(String label);
Map<String, Object> getSelectedValues();
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class Selection {
private final Evaluator<?> evaluator;
private final String name;
public Selection(final Evaluator<?> evaluator, final String name) {
this.evaluator = evaluator;
this.name = name;
}
public String getName() {
return name;
}
public Evaluator<?> getEvaluator() {
return evaluator;
}
}

View File

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator;
public abstract class BooleanEvaluator implements Evaluator<Boolean> {
public Class<? extends Boolean> getType() {
return Boolean.class;
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator;
import java.util.Map;
public interface Evaluator<T> {
public static final String MESSAGE_KEY = "message";
T evaluate(Map<String, Object> objectMap);
Class<? extends T> getType();
}

View File

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator;
public abstract class IntegerEvaluator implements Evaluator<Integer> {
public Class<? extends Integer> getType() {
return Integer.class;
}
}

View File

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator;
public abstract class StringEvaluator implements Evaluator<String> {
public Class<? extends String> getType() {
return String.class;
}
}

View File

@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import java.util.Collection;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Field;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public abstract class AbstractComparisonEvaluator extends BooleanEvaluator {
private final Evaluator<?> lhs;
private final Evaluator<?> rhs;
public AbstractComparisonEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
public final Boolean evaluate(final Map<String, Object> objectMap) {
final Object lhsValue = lhs.evaluate(objectMap);
if ( lhsValue == null ) {
return false;
}
final Object rhsValue = rhs.evaluate(objectMap);
if ( rhsValue == null ) {
return false;
}
return compareRaw(lhsValue, rhsValue);
}
private Boolean compareRaw(Object lhsValue, Object rhsValue) {
if ( lhsValue == null || rhsValue == null ) {
return false;
}
if ( lhsValue instanceof HL7Field ) {
lhsValue = ((HL7Field) lhsValue).getValue();
}
if ( rhsValue instanceof HL7Field ) {
rhsValue = ((HL7Field) rhsValue).getValue();
}
if ( lhsValue == null || rhsValue == null ) {
return false;
}
// both are collections, and compare(lhsValue, rhsValue) is false.
// this would be the case, for instance, if we compared field 1 of one segment to
// a field in another segment, and both fields had components.
if ( lhsValue instanceof Collection && rhsValue instanceof Collection ) {
return false;
}
// if one side is a collection but the other is not, check if any element in that
// collection compares to the other element in a way that satisfies the condition.
// this would happen, for instance, if we check Segment1.Field5 = 'X' and field 5 repeats
// with a value "A~B~C~X~Y~Z"; in this case we do want to consider Field 5 = X as true.
if ( lhsValue instanceof Collection ) {
for ( final Object lhsObject : (Collection<?>) lhsValue ) {
if ( compareRaw(lhsObject, rhsValue) ) {
return true;
}
}
return false;
}
if ( rhsValue instanceof Collection ) {
for ( final Object rhsObject : (Collection<?>) rhsValue ) {
if ( compareRaw(rhsObject, lhsValue) ) {
return true;
}
}
return false;
}
if ( lhsValue != null && rhsValue != null && compare(lhsValue, rhsValue) ) {
return true;
}
return false;
}
protected abstract boolean compare(Object lhs, Object rhs);
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import java.util.regex.Pattern;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public abstract class AbstractNumericComparison extends AbstractComparisonEvaluator {
private static final Pattern NUMERIC_PATTERN = Pattern.compile("\\d+(\\.\\d+)?");
public AbstractNumericComparison(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected final boolean compare(final Object lhs, final Object rhs) {
final Double lhsDouble = toDouble(lhs);
if ( lhsDouble == null ) {
return false;
}
final Double rhsDouble = toDouble(rhs);
if ( rhsDouble == null ) {
return false;
}
return compareNumbers(lhsDouble, rhsDouble);
}
private Double toDouble(final Object value) {
if ( value == null ) {
return null;
}
if ( value instanceof Double ) {
return (Double) value;
}
if ( value instanceof Number ) {
return ((Number) value).doubleValue();
}
if ( value instanceof String ) {
if ( NUMERIC_PATTERN.matcher((String) value).matches() ) {
return Double.parseDouble((String) value);
}
}
return null;
}
protected abstract boolean compareNumbers(final Double lhs, final Double rhs);
}

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class EqualsEvaluator extends AbstractComparisonEvaluator {
public EqualsEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compare(final Object lhs, final Object rhs) {
return lhs != null && rhs != null && ((lhs == rhs) || (lhs.equals(rhs)) || lhs.toString().equals(rhs.toString()));
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class GreaterThanEvaluator extends AbstractNumericComparison {
public GreaterThanEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compareNumbers(final Double lhs, final Double rhs) {
return lhs > rhs;
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class GreaterThanOrEqualEvaluator extends AbstractNumericComparison {
public GreaterThanOrEqualEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compareNumbers(final Double lhs, final Double rhs) {
return lhs >= rhs;
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import java.util.Collection;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class IsNullEvaluator extends BooleanEvaluator {
private final Evaluator<?> subjectEvaluator;
public IsNullEvaluator(final Evaluator<?> subjectEvaluator) {
this.subjectEvaluator = subjectEvaluator;
}
@Override
public Boolean evaluate(final Map<String, Object> objectMap) {
Object subjectValue = subjectEvaluator.evaluate(objectMap);
if ( subjectValue == null ) {
return true;
}
return isNull(subjectValue);
}
private boolean isNull(Object subjectValue) {
if ( subjectValue == null ) {
return true;
}
if ( subjectValue instanceof HL7Component ) {
subjectValue = ((HL7Component) subjectValue).getValue();
}
if ( subjectValue instanceof Collection ) {
final Collection<?> collection = (Collection<?>) subjectValue;
if ( collection.isEmpty() ) {
return true;
}
for ( final Object obj : collection ) {
if ( !isNull(obj) ) {
return false;
}
}
return true;
}
return subjectValue == null;
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class LessThanEvaluator extends AbstractNumericComparison {
public LessThanEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compareNumbers(final Double lhs, final Double rhs) {
return lhs < rhs;
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class LessThanOrEqualEvaluator extends AbstractNumericComparison {
public LessThanOrEqualEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compareNumbers(final Double lhs, final Double rhs) {
return lhs <= rhs;
}
}

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class NotEqualsEvaluator extends AbstractComparisonEvaluator {
public NotEqualsEvaluator(final Evaluator<?> lhs, final Evaluator<?> rhs) {
super(lhs, rhs);
}
@Override
protected boolean compare(final Object lhs, final Object rhs) {
return lhs != null && rhs != null && lhs != rhs && !lhs.equals(rhs) && !lhs.toString().equals(rhs.toString());
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
public class NotEvaluator extends BooleanEvaluator {
private final BooleanEvaluator subjectEvaluator;
public NotEvaluator(final BooleanEvaluator subjectEvaluator) {
this.subjectEvaluator = subjectEvaluator;
}
@Override
public Boolean evaluate(final Map<String, Object> objectMap) {
final Boolean subjectValue = subjectEvaluator.evaluate(objectMap);
return (subjectValue == null || Boolean.TRUE.equals(subjectValue));
}
}

View File

@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.comparison;
import java.util.Collection;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class NotNullEvaluator extends BooleanEvaluator {
private final Evaluator<?> subjectEvaluator;
public NotNullEvaluator(final Evaluator<?> subjectEvaluator) {
this.subjectEvaluator = subjectEvaluator;
}
@Override
public Boolean evaluate(final Map<String, Object> objectMap) {
Object subjectValue = subjectEvaluator.evaluate(objectMap);
if ( subjectValue == null ) {
return false;
}
return isNotNull(subjectValue);
}
private boolean isNotNull(Object subjectValue) {
if ( subjectValue instanceof HL7Component ) {
subjectValue = ((HL7Component) subjectValue).getValue();
}
if ( subjectValue instanceof Collection ) {
final Collection<?> collection = (Collection<?>) subjectValue;
if ( collection.isEmpty() ) {
return false;
}
for ( final Object obj : collection ) {
if ( isNotNull(obj) ) {
return true;
}
}
return false;
}
return subjectValue != null;
}
}

View File

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.literal;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.IntegerEvaluator;
public class IntegerLiteralEvaluator extends IntegerEvaluator {
private final Integer value;
public IntegerLiteralEvaluator(final Integer value) {
this.value = value;
}
@Override
public Integer evaluate(final Map<String, Object> objectMap) {
return value;
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.literal;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.StringEvaluator;
public class StringLiteralEvaluator extends StringEvaluator {
private final String value;
public StringLiteralEvaluator(final String value) {
this.value = value;
}
@Override
public String evaluate(final Map<String, Object> objectMap) {
return value;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.logic;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
public class AndEvaluator extends BooleanEvaluator {
private final BooleanEvaluator lhs;
private final BooleanEvaluator rhs;
public AndEvaluator(final BooleanEvaluator lhs, final BooleanEvaluator rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Boolean evaluate(final Map<String, Object> objectMap) {
final Boolean lhsValue = lhs.evaluate(objectMap);
if ( lhsValue == null || Boolean.FALSE.equals(lhsValue) ) {
return false;
}
final Boolean rhsValue = rhs.evaluate(objectMap);
return (rhsValue != null && Boolean.TRUE.equals(rhsValue));
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.logic;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.BooleanEvaluator;
public class OrEvaluator extends BooleanEvaluator {
private final BooleanEvaluator lhs;
private final BooleanEvaluator rhs;
public OrEvaluator(final BooleanEvaluator lhs, final BooleanEvaluator rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Boolean evaluate(final Map<String, Object> objectMap) {
final Boolean lhsValue = lhs.evaluate(objectMap);
if ( lhsValue != null && Boolean.TRUE.equals(lhsValue) ) {
return true;
}
final Boolean rhsValue = rhs.evaluate(objectMap);
return (rhsValue != null && Boolean.TRUE.equals(rhsValue));
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.message;
import java.util.Map;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
import org.apache.nifi.hl7.query.evaluator.StringEvaluator;
public class DeclaredReferenceEvaluator implements Evaluator<Object> {
private final StringEvaluator referenceNameEvaluator;
public DeclaredReferenceEvaluator(final StringEvaluator referenceNameEvaluator) {
this.referenceNameEvaluator = referenceNameEvaluator;
}
@Override
public Object evaluate(final Map<String, Object> objectMap) {
final String referenceName = referenceNameEvaluator.evaluate(objectMap);
return objectMap.get(referenceName);
}
@Override
public Class<? extends Object> getType() {
return Object.class;
}
}

View File

@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.message;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Component;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.model.HL7Segment;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
import org.apache.nifi.hl7.query.evaluator.IntegerEvaluator;
public class DotEvaluator implements Evaluator<Object> {
private final Evaluator<?> lhs;
private final IntegerEvaluator rhs;
public DotEvaluator(final Evaluator<?> lhs, final IntegerEvaluator rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object evaluate(final Map<String, Object> objectMap) {
final Object lhsValue = this.lhs.evaluate(objectMap);
final Integer rhsValue = this.rhs.evaluate(objectMap);
if ( lhsValue == null || rhsValue == null ) {
return null;
}
final List<Object> results = new ArrayList<>();
if ( lhsValue instanceof Collection ) {
final Collection<?> lhsCollection = (Collection<?>) lhsValue;
for ( final Object obj : lhsCollection ) {
final Object val = getValue(obj, rhsValue);
results.add(val);
}
} else {
final Object val = getValue(lhsValue, rhsValue);
return val;
}
return results;
}
private Object getValue(final Object lhsValue, final int rhsValue) {
final List<?> list;
if ( lhsValue instanceof HL7Message ) {
list = ((HL7Message) lhsValue).getSegments();
} else if ( lhsValue instanceof HL7Segment ) {
list = ((HL7Segment) lhsValue).getFields();
} else if ( lhsValue instanceof HL7Component ) {
list = ((HL7Component) lhsValue).getComponents();
} else {
return null;
}
if ( rhsValue > list.size() ) {
return null;
}
// convert from 0-based to 1-based
return list.get(rhsValue - 1);
}
@Override
public Class<? extends Object> getType() {
return Object.class;
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Field;
import org.apache.nifi.hl7.model.HL7Segment;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
import org.apache.nifi.hl7.query.evaluator.IntegerEvaluator;
@SuppressWarnings("rawtypes")
public class FieldEvaluator implements Evaluator<List> {
private final SegmentEvaluator segmentEvaluator;
private final IntegerEvaluator indexEvaluator;
public FieldEvaluator(final SegmentEvaluator segmentEvaluator, final IntegerEvaluator indexEvaluator) {
this.segmentEvaluator = segmentEvaluator;
this.indexEvaluator = indexEvaluator;
}
public List<HL7Field> evaluate(final Map<String, Object> objectMap) {
final List<HL7Segment> segments = segmentEvaluator.evaluate(objectMap);
if ( segments == null ) {
return Collections.emptyList();
}
final Integer index = indexEvaluator.evaluate(objectMap);
if ( index == null ) {
return Collections.emptyList();
}
final List<HL7Field> fields = new ArrayList<>();
for ( final HL7Segment segment : segments ) {
final List<HL7Field> segmentFields = segment.getFields();
if ( segmentFields.size() <= index ) {
continue;
}
fields.add(segmentFields.get(index));
}
return fields;
}
public Class<? extends List> getType() {
return List.class;
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.message;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
public class MessageEvaluator implements Evaluator<HL7Message> {
public HL7Message evaluate(final Map<String, Object> objectMap) {
return (HL7Message) objectMap.get(Evaluator.MESSAGE_KEY);
}
public Class<? extends HL7Message> getType() {
return HL7Message.class;
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.evaluator.message;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.model.HL7Segment;
import org.apache.nifi.hl7.query.evaluator.Evaluator;
import org.apache.nifi.hl7.query.evaluator.StringEvaluator;
@SuppressWarnings("rawtypes")
public class SegmentEvaluator implements Evaluator<List> {
private final StringEvaluator segmentTypeEvaluator;
public SegmentEvaluator(final StringEvaluator segmentTypeEvaluator) {
this.segmentTypeEvaluator = segmentTypeEvaluator;
}
public List<HL7Segment> evaluate(final Map<String, Object> objectMap) {
final String segmentType = segmentTypeEvaluator.evaluate(objectMap);
if ( segmentType == null ) {
return Collections.emptyList();
}
final HL7Message message = (HL7Message) objectMap.get(Evaluator.MESSAGE_KEY);
final List<HL7Segment> segments = message.getSegments(segmentType);
return (segments == null) ? Collections.<HL7Segment>emptyList() : segments;
}
public Class<? extends List> getType() {
return List.class;
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.exception;
public class HL7QueryParsingException extends RuntimeException {
private static final long serialVersionUID = 1L;
public HL7QueryParsingException() {
super();
}
public HL7QueryParsingException(final Throwable cause) {
super(cause);
}
public HL7QueryParsingException(final String message) {
super(message);
}
public HL7QueryParsingException(final String message, final Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.result;
import java.util.ArrayList;
import java.util.List;
import org.apache.nifi.hl7.query.QueryResult;
import org.apache.nifi.hl7.query.ResultHit;
import org.apache.nifi.hl7.query.Selection;
public class MissedResult implements QueryResult {
private final List<Selection> selections;
public MissedResult(final List<Selection> selections) {
this.selections = selections;
}
@Override
public List<String> getLabels() {
final List<String> labels = new ArrayList<>();
for ( final Selection selection : selections ) {
labels.add(selection.getName());
}
return labels;
}
@Override
public boolean isMatch() {
return false;
}
@Override
public ResultHit nextHit() {
return null;
}
@Override
public int getHitCount() {
return 0;
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.result;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.nifi.hl7.query.QueryResult;
import org.apache.nifi.hl7.query.ResultHit;
import org.apache.nifi.hl7.query.Selection;
public class StandardQueryResult implements QueryResult {
private final List<Selection> selections;
private final Set<Map<String, Object>> hits;
private final Iterator<Map<String, Object>> hitIterator;
public StandardQueryResult(final List<Selection> selections, final Set<Map<String, Object>> hits) {
this.selections = selections;
this.hits = hits;
hitIterator = hits.iterator();
}
@Override
public boolean isMatch() {
return !hits.isEmpty();
}
@Override
public List<String> getLabels() {
final List<String> labels = new ArrayList<>();
for ( final Selection selection : selections ) {
labels.add(selection.getName());
}
return labels;
}
@Override
public int getHitCount() {
return hits.size();
}
@Override
public ResultHit nextHit() {
if ( hitIterator.hasNext() ) {
return new StandardResultHit(hitIterator.next());
} else {
return null;
}
}
}

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query.result;
import java.util.Collections;
import java.util.Map;
import org.apache.nifi.hl7.query.ResultHit;
public class StandardResultHit implements ResultHit {
private final Map<String, Object> values;
public StandardResultHit(final Map<String, Object> values) {
this.values = values;
}
@Override
public Object getValue(final String label) {
return values.get(label);
}
@Override
public Map<String, Object> getSelectedValues() {
return Collections.unmodifiableMap(values);
}
}

View File

@ -0,0 +1,352 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.hl7.query;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.nifi.hl7.hapi.HapiMessage;
import org.apache.nifi.hl7.model.HL7Field;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.query.HL7Query;
import org.apache.nifi.hl7.query.QueryResult;
import org.junit.Test;
import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.HapiContext;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
@SuppressWarnings("resource")
public class TestHL7Query {
@Test
public void testAssignAliases() {
final LinkedHashMap<String, List<Object>> possibleValueMap = new LinkedHashMap<>();
final List<Object> valuesA = new ArrayList<>();
valuesA.add("a");
valuesA.add("b");
valuesA.add("c");
final List<Object> valuesB = new ArrayList<>();
valuesB.add("d");
final List<Object> valuesC = new ArrayList<>();
valuesC.add("e");
valuesC.add("f");
final List<Object> valuesD = new ArrayList<>();
valuesD.add("g");
valuesD.add("h");
possibleValueMap.put("A", valuesA);
possibleValueMap.put("B", valuesB);
possibleValueMap.put("C", valuesC);
possibleValueMap.put("D", valuesD);
for (int i=0; i < valuesA.size() * valuesB.size() * valuesC.size() * valuesD.size(); i++) {
System.out.println(i + " : " + HL7Query.assignAliases(possibleValueMap, i));
}
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 0), "a", "d", "e", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 1), "b", "d", "e", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 2), "c", "d", "e", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 3), "a", "d", "f", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 4), "b", "d", "f", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 5), "c", "d", "f", "g");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 6), "a", "d", "e", "h");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 7), "b", "d", "e", "h");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 8), "c", "d", "e", "h");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 9), "a", "d", "f", "h");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 10), "b", "d", "f", "h");
verifyAssignments(HL7Query.assignAliases(possibleValueMap, 11), "c", "d", "f", "h");
}
private void verifyAssignments(final Map<String, Object> map, final String a, final String b, final String c, final String d) {
assertEquals(a, map.get("A"));
assertEquals(b, map.get("B"));
assertEquals(c, map.get("C"));
assertEquals(d, map.get("D"));
}
@Test
public void testSelectMessage() throws HL7Exception, IOException {
final HL7Query query = HL7Query.compile("SELECT MESSAGE");
final HL7Message msg = createMessage(new File("src/test/resources/vaers-message-long"));
final QueryResult result = query.evaluate(msg);
assertTrue(result.isMatch());
final List<String> labels = result.getLabels();
assertEquals(1, labels.size());
assertEquals("MESSAGE", labels.get(0));
assertEquals(1, result.getHitCount());
assertEquals(msg, result.nextHit().getValue("MESSAGE"));
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testSelectField() throws HL7Exception, IOException {
final HL7Query query = HL7Query.compile("SELECT PID.5");
final HL7Message msg = createMessage(new File("src/test/resources/unsolicited-vaccine-update-short"));
final QueryResult result = query.evaluate(msg);
assertTrue(result.isMatch());
final List<String> labels = result.getLabels();
assertEquals(1, labels.size());
assertEquals(1, result.getHitCount());
final Object names = result.nextHit().getValue("PID.5");
assertTrue(names instanceof List);
final List<Object> nameList = (List) names;
assertEquals(1, nameList.size());
final HL7Field nameField = (HL7Field) nameList.get(0);
assertEquals("KENNEDY^JOHN^FITZGERALD^JR", nameField.getValue());
}
@Test
public void testSelectAbnormalTestResult() throws HL7Exception, IOException {
final String query = "DECLARE result AS REQUIRED OBX SELECT result WHERE result.7 != 'N' AND result.1 = 1";
final HL7Query hl7Query = HL7Query.compile(query);
final QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/vaers-message-long")));
assertFalse( result.isMatch() );
}
@Test
public void testFieldEqualsString() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'L'");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'H'");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testLessThan() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 < 600");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 < 59");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testCompareTwoFields() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 < result.6.2");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE NOT(result.4 > result.6.3)");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testLessThanOrEqual() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 <= 59");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 <= 600");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 <= 58");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testGreaterThanOrEqual() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 >= 59");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 >= 6");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 >= 580");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testGreaterThan() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 > 58");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 > 6");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.4 > 580");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
}
@Test
public void testDistinctValuesReturned() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result1 AS REQUIRED OBX, result2 AS REQUIRED OBX SELECT MESSAGE WHERE result1.7 = 'L' OR result2.7 != 'H'");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
assertEquals(1, result.getHitCount());
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT result WHERE result.1 = 1");
HL7Message msg = createMessage(new File("src/test/resources/vaers-message-long"));
result = hl7Query.evaluate(msg);
assertTrue( result.isMatch() );
assertEquals(9, result.getHitCount());
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT result WHERE result.1 = 1 AND result.3.1.1 = '30961-7'");
result = hl7Query.evaluate(msg);
assertTrue( result.isMatch() );
assertEquals(1, result.getHitCount());
}
@Test
public void testAndWithParens() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'L' AND result.3.1 = 'GLU'");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'L' AND result.3.1 = 'GLU'");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hyperglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'H' AND result.3.1 = 'GLU'");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.7 = 'H' AND result.3.1 = 'GLU'");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hyperglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE (result.7 = 'H') AND (result.3.1 = 'GLU')");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hyperglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE ((result.7 = 'H') AND (result.3.1 = 'GLU'))");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hyperglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE (( ((result.7 = 'H')) AND ( ((result.3.1 = 'GLU')) )))");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hyperglycemia")));
assertTrue( result.isMatch() );
}
@Test
public void testIsNull() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.999 IS NULL");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.1 IS NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE ZZZ IS NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE OBX IS NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE NK1.1 = '1' AND NK1.8 IS NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/unsolicited-vaccine-update-long")));
assertTrue( result.isMatch() );
}
@Test
public void testNotNull() throws HL7Exception, IOException {
HL7Query hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.999 NOT NULL");
QueryResult result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("DECLARE result AS REQUIRED OBX SELECT MESSAGE WHERE result.1 NOT NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE ZZZ NOT NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertFalse( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE OBX NOT NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/hypoglycemia")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE NK1.1 = '1' AND NK1.33 NOT NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/unsolicited-vaccine-update-long")));
assertTrue( result.isMatch() );
hl7Query = HL7Query.compile("SELECT MESSAGE WHERE NK1.1 = 1 AND NK1.33 NOT NULL");
result = hl7Query.evaluate(createMessage(new File("src/test/resources/unsolicited-vaccine-update-long")));
assertTrue( result.isMatch() );
}
private HL7Message createMessage(final File file) throws HL7Exception, IOException {
final byte[] bytes = Files.readAllBytes(file.toPath());
final String msgText = new String(bytes, "UTF-8");
final HapiContext hapiContext = new DefaultHapiContext();
hapiContext.setValidationContext(ValidationContextFactory.noValidation());
final PipeParser parser = hapiContext.getPipeParser();
final Message message = parser.parse(msgText);
return new HapiMessage(message);
}
@Test
@SuppressWarnings("unused")
public void createMessage() throws IOException, HL7Exception {
final byte[] bytes = Files.readAllBytes(Paths.get("src/test/resources/vaers-message-long"));
final String msgText = new String(bytes, "UTF-8");
final HapiContext hapiContext = new DefaultHapiContext();
hapiContext.setValidationContext(ValidationContextFactory.noValidation());
final PipeParser parser = hapiContext.getPipeParser();
final Message message = parser.parse(msgText);
final HL7Message hl7Msg = new HapiMessage(message);
}
}

View File

@ -0,0 +1,5 @@
MSH|^~\&|CERNER||PriorityHealth||||ORU^R01|Q479004375T431430612|P|2.3|
PID|||001677980||SMITH^CURTIS||19680219|M||||||||||929645156318|123456789|
PD1||||1234567890^LAST^FIRST^M^^^^^NPI|
OBR|1|341856649^HNAM_ORDERID|000002006326002362|648088^Basic Metabolic Panel|||20061122151600|||||||||1620^Hooker^Robert^L||||||20061122154733|||F|||||||||||20061122140000|
OBX|1|NM|GLU^Glucose Lvl|159|mg/dL|65-99^65^99|H|||F|||20061122154733|

View File

@ -0,0 +1,5 @@
MSH|^~\&|CERNER||PriorityHealth||||ORU^R01|Q479004375T431430612|P|2.3|
PID|||001677980||SMITH^CURTIS||19680219|M||||||||||929645156318|123456789|
PD1||||1234567890^LAST^FIRST^M^^^^^NPI|
OBR|1|341856649^HNAM_ORDERID|000002006326002362|648088^Basic Metabolic Panel|||20061122151600|||||||||1620^Hooker^Robert^L||||||20061122154733|||F|||||||||||20061122140000|
OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20061122154733|

View File

@ -0,0 +1,23 @@
MSH|^~\&|Lab1^1234^CLIA|^1234^CLIA|ELR^2.16.840.1.113883.19.3.2^ISO|SPH^2.16.840.1.113883.19.3.2^ISO|20110410140502-0500||ORU^R01^ORU_R01|1234567890|P^T|2.5.1|||NE|NE|USA||||USELR1.0^^2.16.840.1.114222.4.10.3^ISO
SFT|1|Level Seven Healthcare Software, Inc.^L^^^^&2.16.840.1.113883.19.4.6^ISO^XX^^^1234|1.2|An Lab System|56734||20080817
PID|1||36363636^^^MPI&2.16.840.1.113883.19.3.2.1&ISO^MR^A&2.16.840.1.113883.19.3.2.1&ISO~444333333^^^&2.16.840.1.113883.4.1^IS O^SS||Everyman^Adam^A^^^^L^^^^^^^BS|Mum^Martha^M^^^^M|19800602|M||2106-3^White^CDCREC^^^^04/24/2007|2222 Home Street^^Ann Arbor^MI^99999^USA^H||^PRN^PH^^1^555^5552004|^WPN^PH^^1^955^5551009|eng^English^ISO6392^^^^3/29/2007|M^Married^HL70002^^^^2.5.1||||||N^Not Hispanic or Latino^HL70189^^^^2.5.1||||||||N|||200808151000-0700| Reliable^2.16.840.1.113883.19.3.1^ISO
ORC|RE|23456^EHR^2.16.840.1.113883.19.3.2.3^ISO|9700123^Lab^2.16.840.1.113883.19.3.1.6^ISO|||||||||1234^Admit^Alan^A^III^Dr^^^&2.16.840.1.113883.19.4.6^ISO^L^^^EI^&2.16.840.1.113883.19.4.6^ISO^^^^^^^^MD||^WPN^PH^^1^555^5551005|||||||Level Seven Healthcare, Inc.^L^^^^&2.16.840.1.113883.19.4.6^ISO^XX^^^1234|1005 Healthcare Drive^^Ann Arbor^MI^99999^USA^B|^WPN^PH^^1^555^5553001|4444 Healthcare Drive^Suite 123^Ann Arbor^MI^99999^USA^B
OBR|1|23456^EHR^2.16.840.1.113883.19.3.2.3^ISO|9700123^Lab^2.16.840.1.113883.19.3.1.6^ISO|24323-8^Comprehensive metabolic 2000 panel in Serum or Plasma^LN^3436442^Metaboloic Panel 2000, Comprehensive^99USI|||201104101130-0500||||||angina|||1234^Admit^Alan^A^III^Dr^^^&2.16.840.1.113883.19.4.6^ISO^L^^^EI^&2.16.840.1.113883.19.4.6^ISO^^^^^^^^MD|^WPN^PH^^1^555^5551005|||||201104101405-0500|||F||||||413^Angina pectoris^I9CDX^^^^07/09/2008|1235&Slide&Stan&S&&Dr&MD&&DOC&2.16.840.1.113883.19.4.6&ISO
OBX|1|NM|17861-6^Calcium [Mass/volume] in Serum or Plasma^LN||27.3|mg/dL^milligrams per deciliter^UCUM|8.7-10.7|HH|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|2|NM|3094-0^Urea nitrogen [Mass/volume] in Serum of Plasma^LN||15|mg/dL^milligrams per deciliter^UCUM|6 to 23|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|3|NM|2160-0^Creatinine [Mass/volume] in Serum or Plasma^LN||1.8|mg/dL^milligrams per deciliter^UCUM|0.7 to 1.2|H|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|4|NM|3097-3^Urea nitrogen/Creatinine [Mass ratio] in Serum or Plasma^LN||15||6 to 25|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|5|NM|2885-2^Protein [Mass/volume] in Serum or Plasma^LN||8.9|gm/dL^grams per deciliter^UCUM|6.3 to 8.2|H|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|6|NM|1751-7^Albumin [Mass/volume] in Serum or Plasma^LN||5.7|gm/dL^grams per deciliter^UCUM|3.5 to 5.0|H|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|7|NM|2336-6^Globulin [Mass/volume] in Serum or Plasma^LN||4.7|gm/dL^grams per deciliter^UCUM|2.2 to 4.2|H|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|8|NM|1759-0^Albumin/Globulin [Mass ratio] in Serum or Plasma^LN||1.7||0.8 to 2.0|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|9|NM|1975-2^Bilirubin.total [Mass/volume] in Serum or Plasma^LN||0.7|mg/dL^milligrams per deciliter^UCUM|0.3 to 1.9|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|10|NM|2345-7^Glucose [Mass/volume] in Serum or Plasma^LN||55|mg/dL^milligrams per deciliter^UCUM|60 to 109|L|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|11|NM|6768-6^Alkaline phosphatase [Enzymatic activity/volume] in Serum or Plasma^LN||64|U/L^units per liter^UCUM|32 to 110|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|12|NM|1920-8^Aspartate aminotransferase [Enzymatic activity/volume] in Serum or Plasma^LN||6|U/L^units per liter^UCUM|6 to 18|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|13|NM|1742-6^Alanine aminotransferase [Enzymatic activity/volume] in Serum or Plasma^LN||10|U/L^units per liter^UCUM|5 to 35|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|14|NM|2951-2^Sodium [Moles/volume] in Serum or Plasma^LN||140|mmol/L^millimoles per liter^UCUM|137 to 147|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|15|NM|2823-3^Potassium [Moles/volume] in Serum or Plasma^LN||4.5|mmol/L^millimoles per liter^UCUM|3.4 to 5.3|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|16|NM|2075-0^Chloride [Moles/volume] in Serum or Plasma^LN||99|mmol/L^millimoles per liter^UCUM|99 to 108|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
OBX|17|NM|2028-9^Carbon dioxide, total [Moles/volume] in Serum or Plasma^LN||27|mmol/L^millimoles per liter^UCUM|22 to 29|N|||F|||201104101130-0500|||||201104101325-0500||||GHH Lab^L^^^^CLIA&2.16.840.1.113883.19.4.6&ISO^XX^^^1236|3434 Industrial Loop^^Ann Arbor^MI^99999^USA^B|9876543^Slide^Stan^S^^^^^NPPES&2.16.840.1.113883.19.4.6&ISO^L^^^NPI
SPM|1|23456&EHR&2.16.840.1.113883.19.3.2.3&ISO^9700122&Lab&2.16.840.1.113883.19.3.1.6&ISO||119364003^Serum specimen^SCT^^^^20080131|||||||||||||201104101130-0500|201104101130-0500

View File

@ -0,0 +1,16 @@
MSH|^~\&||MA0000||GA0000|19970901||VXU^V04|19970522MA53|T|2.3.1|||AL
PID|||1234^^^^SR^~1234-12^^^^LR^~3872^^^^MR~221345671^^^^SS^~430078856^^^^MA^ ||KENNEDY^JOHN^FITZGERALD^JR^^^L|BOUVIER^^^^^^M|19900607|M|KENNEDY^BABY BOY^^^^^^ B|W^WHITE^NY8 RACE CODES^W^WHITE^HL70005|123 MAIN ST^APT 3B^LEXINGTON^MA^00210^ ^M^MSA CODE^MA034~345 ELM ST^^BOSTON^MA^00314^^BLD~^^^^^^BR^^MA002| |(617) 555-1212 ^PRN^PH^^^617^5551212^^||EN^ENGLISH^HL70296^^^|||||||WN^NOT HISPANIC^LOCAL CODE SET^NH^NOT OF HISPANIC ORIGIN^HL70189|CHILDREN=S HOSPITAL
PD1|||CHILDREN=S HOSPITAL^^1234^^^^XX~LEXINGTON CLINIC^^1234A^^^^FI|12345^CARE^ PRIMARY^^^DR^MD^^^L^^^DN|||||||03^REMINDER/RECALL - NO CALLS^HL70215|Y
NK1|1|KENNEDY^JACQUELINE^LEE|32^MOTHER^HL70063||||||||||||||||||||||||||||||898666725^^^^SS
NK1|2|KENNEDY^JOHN^FITZGERALD|33^FATHER^HL70063||||||||||||||||||||||||||||||822546618^^^^SS
PV1||R|||||||||||||||A|||V02^19900607~H02^19900607
RXA|0|1|19900607|19900607|08^HEPB-PEDIATRIC/ADOLESCENT^CVX^90744^HEPB-PEDATRIC/ADOLESCENT^CPT|.5|ML^^ISO+||03^HISTORICAL INFORMATION - FROM PARENT=S WRITTEN RECORD^NIP0001|^JONES^LISA|^^^CHILDREN=S HOSPITAL||5|MCG^^ISO+|MRK12345| 199206|MSD^MERCK^MVX
RXA|0|4|19910907|19910907|50^DTAP-HIB^CVX^90721^DTAP-HIB^CPT|.5|ML^^ISO+||00^NEW IMMUNIZATION RECORD^NIP0001|1234567890^SMITH^SALLY^S^^^^^^^^^VEI~1234567891 ^O=BRIAN^ROBERT^A^^DR^MD^^^^^^OEI|^^^CHILD HEALTHCARE CLINIC^^^^^101 MAIN STREET^^ BOSTON^MA||||W46932777|199208|PMC^PASTEUR MERIEUX CONNAUGHT^MVX|||CP|A| 19910907120030
RXR|IM^INTRAMUSCULAR^HL70162|LA^LEFT ARM^HL70163
RXA|0|1|19910907|19910907|03^MMR^CVX|.5|ML^^ISO+|||1234567890^SMITH^SALLY^S^^^^^^^^^VEI~1234567891^O=BRIAN^ROBERT^A^^DR^MD^^^^^^OEI|^^^CHILD HEALTHCARE CLINIC^^^^^101 MAIN STREET^^BOSTON^MA||||W2348796456|19920731|MSD^MERCK^MVX
RXR|SC^SUBCUTANEOUS^HL70162|LA^LEFT ARM^HL70163
RXA|0|5|19950520|19950520|20^DTAP^CVX|.5|ML^^ISO+|||1234567891^O=BRIAN^ROBERT^A^^DR|^^^CHILD HEALTHCARE CLINIC^^^^^101 MAIN STREET^^BOSTON^MA||||W22532806|19950705|PMC^ PASTEUR MERIEUX CONNAUGHT^MVX
RXR|IM^INTRAMUSCULAR^HL70162|LA^LEFT ARM^HL70163
NTE|PATIENT DEVELOPED HIGH FEVER APPROX 3 HRS AFTER VACCINE INJECTION
RXA|0|2|19950520|19950520|03^MMR^CVX|.5|ML^^ISO+|||1234567891^O=BRIAN^ROBERT^A^^DR|^^^CHILD HEALTHCARE CLINIC^^^^^101 MAIN STREET^^BOSTON^MA||||W2341234567|19950630| MSD^MERCK^MVX
RXR|SC^SUBCUTANEOUS^HL70162|LA^LEFT ARM^HL70163

View File

@ -0,0 +1,4 @@
MSH|^~\&|||||||VXU^V04|19970522MA53|P|2.3.1
PID|||221345671^^^^SS||KENNEDY^JOHN^FITZGERALD^JR|BOUVIER^^^^^^M|19900607|M|||^^^^MA^^^BLD
NK1|1|KENNEDY^JACQUELINE^LEE|32^MOTHER^HL70063
RXA|0|1|19900607|19900607|08^HEPB-PEDIATRIC/ADOLESCENT^CVX|.5|ML^^ISO+||||||||MRK12345||MSD^MERCK^MVX

View File

@ -0,0 +1,3 @@
MSH|^~\&||GA0000||MA0000|199705221605||VXQ^V01|19970522GA40|T|2.3.1|||AL
QRD|199705221605|R|I|19970522GA05|||25^RD|^KENNEDY^JOHN^FITZGERALD^JR|VXI^VACCINE INFORMATION^HL70048|^SIIS
QRF|MA0000||||256946789~19900607~MA~MA99999999~88888888~KENNEDY^JACQUELINE^LEE~BOUVIER~898666725~KENNEDY^JOHN^FITZGERALD~822546618

View File

@ -0,0 +1,60 @@
MSH|^~\&||GA0000||VAERS PROCESSOR|20010331605||ORU^R01|20010422GA03|T|2.3.1|||AL|
PID|||1234^^^^SR~1234-12^^^^LR~00725^^^^MR||Doe^John^Fitzgerald^JR^^^L||20001007|M||2106-3^White^HL70005|123 Peachtree St^APT 3B^Atlanta^GA^30210^^M^^GA067||(678) 555-1212^^PRN|
NK1|1|Jones^Jane^Lee^^RN|VAB^Vaccine administered by (Name)^HL70063|
NK1|2|Jones^Jane^Lee^^RN|FVP^Form completed by (Name)-Vaccine provider^HL70063|101 Main Street^^Atlanta^GA^38765^^O^^GA121||(404) 554-9097^^WPN|
ORC|CN|||||||||||1234567^Welby^Marcus^J^Jr^Dr.^MD^L|||||||||Peachtree Clinic|101 Main Street^^Atlanta^GA^38765^^O^^GA121|(404) 554-9097^^WPN|101 Main Street^^Atlanta^GA^38765^^O^^GA121|
OBR|1|||^CDC VAERS-1 (FDA) Report|||20010316|
OBX|1|NM|21612-7^Reported Patient Age^LN||05|mo^month^ANSI|
OBX|1|TS|30947-6^Date form completed^LN||20010316|
OBX|2|FT|30948-4^Vaccination adverse events and treatment, if any^LN|1|fever of 106F, with vomiting, seizures, persistent crying lasting over 3 hours, loss of appetite|
OBX|3|CE|30949-2^Vaccination adverse event outcome^LN|1|E^required emergency room/doctor visit^NIP005|
OBX|4|CE|30949-2^Vaccination adverse event outcome^LN|1|H^required hospitalization^NIP005|
OBX|5|NM|30950-0^Number of days hospitalized due to vaccination adverse event^LN|1|02|d^day^ANSI|
OBX|6|CE|30951-8^Patient recovered^LN||Y^Yes^ HL70239|
OBX|7|TS|30952-6^Date of vaccination^LN||20010216|
OBX|8|TS|30953-4^Adverse event onset date and time^LN||200102180900|
OBX|9|FT|30954-2^Relevant diagnostic tests/lab data^LN||Electrolytes, CBC, Blood culture|
OBR|2|||30955-9^All vaccines given on date listed in #10^LN|
OBX|1|CE30955-9&30956-7^Vaccine type^LN|1|08^HepB-Adolescent/pediatric^CVX|
OBX|2|CE|30955-9&30957-5^Manufacturer^LN|1|MSD^Merck^MVX|
OBX|3|ST|30955-9&30959-1^Lot number^LN|1|MRK12345|
OBX|4|CE|30955-9&30958-3^ Route^LN|1|IM^Intramuscular ^HL70162|
OBX|5|CE|30955-9&31034-2^Site^LN|1|LA^Left arm^ HL70163|
OBX|6|NM|30955-9&30960-9^Number of previous doses^LN|1|01I
OBX|7|CE|CE|30955-9&30956-7^Vaccine type^LN|2|50^DTaP-Hib^CVX|
OBX|8|CE|30955-9&30957-5^ Manufacturer^LN|2|WAL^Wyeth_Ayerst^MVX|
OBX|9|ST|30955-9&30959-1^Lot number^LN|2|W46932777|
OBX|10|CE|30955-9&30958-3^ Route^LN|2|IM^Intramuscular^HL70162|
OBX|11|CE|30955-9&31034-2^Site^LN|2|LA^Left arm^HL70163|
OBX|12|NM|30955-9&30960-9^Number of previous doses^LN|2|01|
OBR|3|||30961-7^Any other vaccinations within 4 weeks prior to the date listed in #10|
OBX|1|CE|30961-7&30956-7^Vaccine type^LN|1|10^IPV^CVX|
OBX|2|CE|30961-7&30957-5^Manufacturer^LN|1|PMC^Aventis Pasteur ^MVX|
OBX|3|ST|30961-7&30959-1^Lot number^LN|1|PMC123456|
OBX|4|CE|30961-7&30958-3^Route^LN|1|SC^Subcutaneaous^HL70162|
OBX|5|CE|30961-7&31034-2^Site^LN|1|LA^Left arm^HL70163|
OBX|6|NM|30961-7&30960-9^Number of previous doses^LN|1|01|
OBX|7|TS|30961-7&31035-9^date given^LN|1|20001216|
OBX|8|CE|30962-^Vaccinated at^LN||PVT^Private doctor<6F>s office/hospital^NIP009|
OBX|9|CE|30963-3^Vaccine purchased with^LN||PBF^Public funds^NIP008|
OBX|10|FT|30964-1^Other medications^LN||None|
OBX|11|FT|30965-8^Illness at time of vaccination (specify)^LN||None|
OBX|12|FT|30966-6^Pre-existing physician diagnosed allergies, birth defects, medical conditions^LN||Past conditions convulsions|
OBX|13|CE|30967-4^Was adverse event reported previously^LN||N^no^NIP009|
OBR|4||30968-2^Adverse event following prior vaccination in patient^LN|
OBX|1|TX|30968-2&30971-6^Adverse event^LN||None|
OBR|5||30969-0^Adverse event following prior vaccination in brother^LN|
OBX|1|TX||30969-0&30971-6^Adverse event^LN||vomiting, fever, otitis media|
OBX|2|NM||30969-0&30972-4^Onset age^LN||04|mo^month^ANSI|
OBX|3|CE||30969-0&30956-7^Vaccine Type ^LN||10^IPV^CVX|
OBX|4|NM||30969-0&30973-2^Dose number in series^LN||02|
OBR|6|||30970-8^Adverse event following prior vaccination in sister^LN|
OBX|1|TX|30970-8&30971-6^Adverse event^LN||None|
OBR|7||^For children 5 and under|
OBX|1|NM|8339-4^Body weight at birth^LN||82|oz^ounces^ANSI|
OBX|2|NM|30974-0^Number of brothers and sisters^LN||2|
OBR|8|||^Only for reports submitted by manufacturer/immunization project|
OBX|1|ST|30975-7^Mfr./Imm. Proj. report no.^LN||12345678|
OBX|2|TS|30976-5^Date received by manufacturer/immunization project^LN||12345678|
OBX|3|CE|30977-3^15 day report^LN||N^No^HL70136|
OBX|4|CE|30978-1^Report type^LN||IN^Initial^NIP010|

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-hl7-bundle</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>nifi-hl7-nar</artifactId>
<packaging>nar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-hl7-processors</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1 @@
/target/

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-hl7-bundle</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>nifi-hl7-processors</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-processor-utils</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-hl7-query-language</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-base</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v21</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v22</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v23</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v231</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v24</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v25</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v251</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi</groupId>
<artifactId>hapi-structures-v26</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,247 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.processors.hl7;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.nifi.annotation.behavior.SideEffectFree;
import org.apache.nifi.annotation.behavior.SupportsBatching;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.io.InputStreamCallback;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.stream.io.StreamUtils;
import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.HapiContext;
import ca.uhn.hl7v2.model.Composite;
import ca.uhn.hl7v2.model.Group;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.Primitive;
import ca.uhn.hl7v2.model.Segment;
import ca.uhn.hl7v2.model.Structure;
import ca.uhn.hl7v2.model.Type;
import ca.uhn.hl7v2.model.Varies;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
@SideEffectFree
@SupportsBatching
@Tags({"HL7", "health level 7", "healthcare", "extract", "attributes"})
@CapabilityDescription("Extracts information from an HL7 (Health Level 7) formatted FlowFile and adds the information as FlowFile Attributes. "
+ "The attributes are named as <Segment Name> <dot> <Field Index>. If the segment is repeating, the naming will be "
+ "<Segment Name> <underscore> <Segment Index> <dot> <Field Index>. For example, we may have an attribute named \"MHS.12\" with "
+ "a value of \"2.1\" and an attribute named \"OBX_11.3\" with a value of \"93000^CPT4\".")
public class ExtractHL7Attributes extends AbstractProcessor {
public static final PropertyDescriptor CHARACTER_SET = new PropertyDescriptor.Builder()
.name("Character Encoding")
.description("The Character Encoding that is used to encode the HL7 data")
.required(true)
.expressionLanguageSupported(true)
.addValidator(StandardValidators.CHARACTER_SET_VALIDATOR)
.defaultValue("UTF-8")
.build();
public static final Relationship REL_SUCCESS = new Relationship.Builder()
.name("success")
.description("A FlowFile is routed to this relationship if it is properly parsed as HL7 and its attributes extracted")
.build();
public static final Relationship REL_FAILURE = new Relationship.Builder()
.name("failure")
.description("A FlowFile is routed to this relationship if it cannot be mapped to FlowFile Attributes. This would happen if the FlowFile does not contain valid HL7 data")
.build();
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
final List<PropertyDescriptor> properties = new ArrayList<>();
properties.add(CHARACTER_SET);
return properties;
}
@Override
public Set<Relationship> getRelationships() {
final Set<Relationship> relationships = new HashSet<>();
relationships.add(REL_SUCCESS);
relationships.add(REL_FAILURE);
return relationships;
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
FlowFile flowFile = session.get();
if ( flowFile == null ) {
return;
}
final Charset charset = Charset.forName(context.getProperty(CHARACTER_SET).evaluateAttributeExpressions(flowFile).getValue());
final byte[] buffer = new byte[(int) flowFile.getSize()];
session.read(flowFile, new InputStreamCallback() {
@Override
public void process(final InputStream in) throws IOException {
StreamUtils.fillBuffer(in, buffer);
}
});
@SuppressWarnings("resource")
final HapiContext hapiContext = new DefaultHapiContext();
hapiContext.setValidationContext(ValidationContextFactory.noValidation());
final PipeParser parser = hapiContext.getPipeParser();
final String hl7Text = new String(buffer, charset);
final Message message;
try {
message = parser.parse(hl7Text);
final Group group = message.getParent();
final Map<String, String> attributes = new HashMap<>();
extractAttributes(group, attributes);
flowFile = session.putAllAttributes(flowFile, attributes);
getLogger().info("Successfully extracted {} attributes for {}; routing to success", new Object[] {attributes.size(), flowFile});
getLogger().debug("Added the following attributes for {}: {}", new Object[] {flowFile, attributes});
session.transfer(flowFile, REL_SUCCESS);
} catch (final HL7Exception e) {
getLogger().error("Failed to extract attributes from {} due to {}", new Object[] {flowFile, e});
session.transfer(flowFile, REL_FAILURE);
return;
}
}
private void extractAttributes(final Group group, final Map<String, String> attributes) throws HL7Exception {
extractAttributes(group, attributes, new HashMap<String, Integer>());
}
private void extractAttributes(final Group group, final Map<String, String> attributes, final Map<String, Integer> segmentCounts) throws HL7Exception {
if ( group.isEmpty() ) {
return;
}
final String[] structureNames = group.getNames();
for ( final String structName : structureNames ) {
final Structure[] subStructures = group.getAll(structName);
if ( group.isGroup(structName) ) {
for ( final Structure subStructure : subStructures ) {
final Group subGroup = (Group) subStructure;
extractAttributes(subGroup, attributes, segmentCounts);
}
} else {
for ( final Structure structure : subStructures ) {
final Segment segment = (Segment) structure ;
final String segmentName = segment.getName();
Integer segmentNum = segmentCounts.get(segmentName);
if (segmentNum == null) {
segmentNum = 1;
segmentCounts.put(segmentName, 1);
} else {
segmentNum++;
segmentCounts.put(segmentName, segmentNum);
}
final boolean segmentRepeating = segment.getParent().isRepeating(segment.getName());
final boolean parentRepeating = (segment.getParent().getParent() != segment.getParent() && segment.getParent().getParent().isRepeating(segment.getParent().getName()));
final boolean useSegmentIndex = segmentRepeating || parentRepeating;
final Map<String, String> attributeMap = getAttributes(segment, useSegmentIndex ? segmentNum : null);
attributes.putAll(attributeMap);
}
}
}
}
private Map<String, String> getAttributes(final Segment segment, final Integer segmentNum) throws HL7Exception {
final Map<String, String> attributes = new HashMap<>();
for (int i=1; i <= segment.numFields(); i++) {
final String fieldName = segment.getName() + (segmentNum == null ? "" : "_" + segmentNum) + "." + i;
final Type[] types = segment.getField(i);
final StringBuilder sb = new StringBuilder();
for ( final Type type : types ) {
final String typeValue = getValue(type);
if ( !typeValue.isEmpty() ) {
sb.append(typeValue).append("^");
}
}
if ( sb.length() == 0 ) {
continue;
}
String typeVal = sb.toString();
if ( typeVal.endsWith("^") ) {
typeVal = typeVal.substring(0, typeVal.length() - 1);
}
attributes.put(fieldName, typeVal);
}
return attributes;
}
private String getValue(final Type type) {
if ( type == null ) {
return "";
}
if ( type instanceof Primitive ) {
final String value = ((Primitive) type).getValue();
return value == null ? "" : value;
} else if ( type instanceof Composite ) {
final StringBuilder sb = new StringBuilder();
final Composite composite = (Composite) type;
for ( final Type component : composite.getComponents() ) {
final String componentValue = getValue(component);
if ( !componentValue.isEmpty() ) {
sb.append(componentValue).append("^");
}
}
final String value = sb.toString();
if ( value.endsWith("^") ) {
return value.substring(0, value.length() - 1);
}
return value;
} else if ( type instanceof Varies ) {
final Varies varies = (Varies) type;
return getValue(varies.getData());
}
return "";
}
}

View File

@ -0,0 +1,217 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.processors.hl7;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.nifi.annotation.behavior.DynamicProperties;
import org.apache.nifi.annotation.behavior.DynamicProperty;
import org.apache.nifi.annotation.behavior.EventDriven;
import org.apache.nifi.annotation.behavior.SideEffectFree;
import org.apache.nifi.annotation.behavior.SupportsBatching;
import org.apache.nifi.annotation.behavior.WritesAttribute;
import org.apache.nifi.annotation.behavior.WritesAttributes;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.components.Validator;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.hl7.hapi.HapiMessage;
import org.apache.nifi.hl7.model.HL7Message;
import org.apache.nifi.hl7.query.HL7Query;
import org.apache.nifi.hl7.query.QueryResult;
import org.apache.nifi.hl7.query.exception.HL7QueryParsingException;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.io.InputStreamCallback;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.stream.io.StreamUtils;
import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HapiContext;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.validation.impl.ValidationContextFactory;
@EventDriven
@SideEffectFree
@SupportsBatching
@Tags({"HL7", "healthcare", "route", "Health Level 7"})
@DynamicProperties({@DynamicProperty(name="Name of a Relationship", value="An HL7 Query Language query", description="If a FlowFile matches the query, it will be routed to a relationship with the name of the property")})
@WritesAttributes({@WritesAttribute(attribute="RouteHL7.Route", description="The name of the relationship to which the FlowFile was routed")})
@CapabilityDescription("Routes incoming HL7 data according to user-defined queries. To add a query, add a new property to the processor."
+ " The name of the property will become a new relationship for the processor, and the value is an HL7 Query Language query. If"
+ " a FlowFile matches the query, a copy of the FlowFile will be routed to the associated relationship.")
public class RouteHL7 extends AbstractProcessor {
public static final PropertyDescriptor CHARACTER_SET = new PropertyDescriptor.Builder()
.name("Character Encoding")
.description("The Character Encoding that is used to encode the HL7 data")
.required(true)
.expressionLanguageSupported(true)
.addValidator(StandardValidators.CHARACTER_SET_VALIDATOR)
.defaultValue("UTF-8")
.build();
static final Relationship REL_FAILURE = new Relationship.Builder()
.name("failure")
.description("Any FlowFile that cannot be parsed as HL7 will be routed to this relationship")
.build();
static final Relationship REL_ORIGINAL = new Relationship.Builder()
.name("original")
.description("The original FlowFile that comes into this processor will be routed to this relationship, unless it is routed to 'failure'")
.build();
private volatile Map<Relationship, HL7Query> queries = new HashMap<>();
@Override
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
return new PropertyDescriptor.Builder()
.name(propertyDescriptorName)
.description("Specifies a query that will cause any HL7 message matching the query to be routed to the '" + propertyDescriptorName + "' relationship")
.required(false)
.dynamic(true)
.addValidator(new HL7QueryValidator())
.build();
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
final List<PropertyDescriptor> properties = new ArrayList<>();
properties.add(CHARACTER_SET);
return properties;
}
@Override
public void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue) {
if ( !descriptor.isDynamic() ) {
return;
}
final Map<Relationship, HL7Query> updatedQueryMap = new HashMap<>(queries);
final Relationship relationship = new Relationship.Builder().name(descriptor.getName()).build();
if ( newValue == null ) {
updatedQueryMap.remove(relationship);
} else {
final HL7Query query = HL7Query.compile(newValue);
updatedQueryMap.put(relationship, query);
}
this.queries = updatedQueryMap;
}
@Override
public Set<Relationship> getRelationships() {
final Set<Relationship> relationships = new HashSet<>(queries.keySet());
relationships.add(REL_FAILURE);
relationships.add(REL_ORIGINAL);
return relationships;
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
FlowFile flowFile = session.get();
if ( flowFile == null ) {
return;
}
final Charset charset = Charset.forName(context.getProperty(CHARACTER_SET).evaluateAttributeExpressions(flowFile).getValue());
final byte[] buffer = new byte[(int) flowFile.getSize()];
session.read(flowFile, new InputStreamCallback() {
@Override
public void process(final InputStream in) throws IOException {
StreamUtils.fillBuffer(in, buffer);
}
});
@SuppressWarnings("resource")
final HapiContext hapiContext = new DefaultHapiContext();
hapiContext.setValidationContext(ValidationContextFactory.noValidation());
final PipeParser parser = hapiContext.getPipeParser();
final String hl7Text = new String(buffer, charset);
final HL7Message message;
try {
final Message hapiMessage = parser.parse(hl7Text);
message = new HapiMessage(hapiMessage);
} catch (final Exception e) {
getLogger().error("Failed to parse {} as HL7 due to {}; routing to failure", new Object[] {flowFile, e});
session.transfer(flowFile, REL_FAILURE);
return;
}
final Set<String> matchingRels = new HashSet<>();
final Map<Relationship, HL7Query> queryMap = queries;
for ( final Map.Entry<Relationship, HL7Query> entry : queryMap.entrySet() ) {
final Relationship relationship = entry.getKey();
final HL7Query query = entry.getValue();
final QueryResult result = query.evaluate(message);
if ( result.isMatch() ) {
FlowFile clone = session.clone(flowFile);
clone = session.putAttribute(clone, "RouteHL7.Route", relationship.getName());
session.transfer(clone, relationship);
session.getProvenanceReporter().route(clone, relationship);
matchingRels.add(relationship.getName());
}
}
session.transfer(flowFile, REL_ORIGINAL);
getLogger().info("Routed a copy of {} to {} relationships: {}", new Object[] {flowFile, matchingRels.size(), matchingRels});
}
private static class HL7QueryValidator implements Validator {
@Override
public ValidationResult validate(final String subject, final String input, final ValidationContext context) {
String error = null;
try {
final HL7Query hl7Query = HL7Query.compile(input);
final List<Class<?>> returnTypes = hl7Query.getReturnTypes();
if ( returnTypes.size() != 1 ) {
error = "RouteHL7 requires that the HL7 Query return exactly 1 element of type MESSAGE";
} else if ( !HL7Message.class.isAssignableFrom(returnTypes.get(0)) ) {
error = "RouteHL7 requires that the HL7 Query return exactly 1 element of type MESSAGE";
}
} catch (final HL7QueryParsingException e) {
error = e.toString();
}
if ( error == null ) {
return new ValidationResult.Builder().subject(subject).input(input).valid(true).build();
} else {
return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(error).build();
}
}
}
}

View File

@ -0,0 +1,16 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
org.apache.nifi.processors.hl7.ExtractHL7Attributes
org.apache.nifi.processors.hl7.RouteHL7

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.processors.hl7;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.nifi.processors.hl7.ExtractHL7Attributes;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Test;
public class TestExtractHL7Attributes {
@Test
public void testExtract() throws IOException {
System.setProperty("org.slf4j.simpleLogger.log.org.apache.nifi", "DEBUG");
final TestRunner runner = TestRunners.newTestRunner(ExtractHL7Attributes.class);
runner.enqueue(Paths.get("src/test/resources/1.hl7"));
runner.run();
runner.assertAllFlowFilesTransferred(ExtractHL7Attributes.REL_SUCCESS, 1);
final MockFlowFile out = runner.getFlowFilesForRelationship(ExtractHL7Attributes.REL_SUCCESS).get(0);
final SortedMap<String, String> sortedAttrs = new TreeMap<>(out.getAttributes());
for (final Map.Entry<String, String> entry : sortedAttrs.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
}

View File

@ -0,0 +1,16 @@
MSH|^~`&|ECG REPORTING|ROCHESTER|ERIS|ROCHESTER|20110621050440||ORU^R01|20110621050440|P|2.1
PID|||999999999||TEST^PATIENT||18450101|F
OBR|||211088491|0^ADULT^ROCHECG|||20110620170631|||||||||M999999^^^^^^^RACFID||||||20110621060232||EC|F|||||||M999999^LASTNAME MD^FIRSTNAME^^^^^RACFID
OBX||ST|93000.2^VENTRICULAR RATE EKG/MIN^CPT4|1|52|/SEC
OBX||ST|93000.4^PR INTERVAL(MSEC)^CPT4|2|208|MSEC
OBX||ST|93000.5^QRS - INTERVAL(MSEC)^CPT4|3|88|MSEC
OBX||ST|93000.6^QT - INTERVAL(MSEC)^CPT4|4|466|MSEC
OBX||ST|93000&PTL^PHYSICAL TEST LOCATION^CPT4|5|STMA
OBX||ST|93000&PTR^PHYSICAL TEST ROOM^CPT4|6|04254
OBX||CE|93000.17^^CPT4|7|21&101^Sinus bradycardia`T`with 1st degree A-V block^MEIECG
OBX||CE|93000.17^^CPT4|8|1687^Otherwise normal ECG^MEIECG
OBX||CE|93000&CMP^^CPT4|9|1301^When compared with ECG of^MEIECG
OBX||TS|93000&CMD^EKG COMPARISON DATE^CPT4|10|201106171659
OBX||CE|93000&CMP^^CPT4|11|1305^No significant change was found^MEIECG
OBX||TX|93000.48^EKG COMMENT^CPT4|12|9917^LASTNAME MD^FIRSTNAME
OBX||FT|93000^ECG 12-LEAD^CPT4|13|{\rtf1\ansi \deff1\deflang1033\ {\fonttbl{\f1\fmodern\fcharset0 Courier;}{\f2\fmodern\fcharset0 Courier;}} \pard\plain \f1\fs18\par 20Jun2011 17:06\par VENTRICULAR RATE 52\par Sinus bradycardia with 1st degree A-V block\par Otherwise normal ECG\par When compared with ECG of 17-JUN-2011 16:59,\par No significant change was found\par 47507`S`'LASTNAME MD`S`'FIRSTNAME \par }

View File

@ -0,0 +1,5 @@
MSH|^~\&|CERNER||PriorityHealth||||ORU^R01|Q479004375T431430612|P|2.3|
PID|||001677980||SMITH^CURTIS||19680219|M||||||||||929645156318|123456789|
PD1||||1234567890^LAST^FIRST^M^^^^^NPI|
OBR|1|341856649^HNAM_ORDERID|000002006326002362|648088^Basic Metabolic Panel|||20061122151600|||||||||1620^Hooker^Robert^L||||||20061122154733|||F|||||||||||20061122140000|
OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20061122154733|

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-bundles</artifactId>
<version>0.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>nifi-hl7-bundle</artifactId>
<packaging>pom</packaging>
<modules>
<module>nifi-hl7-processors</module>
<module>nifi-hl7-nar</module>
</modules>
</project>