mirror of https://github.com/apache/nifi.git
Merge remote-tracking branch 'upstream/develop' into nifi-solr-bundle
Conflicts: nifi/nifi-assembly/pom.xml nifi/nifi-nar-bundles/pom.xml
This commit is contained in:
commit
751d601a92
|
@ -501,6 +501,54 @@ The following binary components are provided under the Apache Software License v
|
||||||
Apache License Version 2.0 http://www.apache.org/licenses/.
|
Apache License Version 2.0 http://www.apache.org/licenses/.
|
||||||
(c) Daniel Lemire, http://lemire.me/en/
|
(c) Daniel Lemire, http://lemire.me/en/
|
||||||
|
|
||||||
|
(ASLv2) Twitter4J
|
||||||
|
The following NOTICE information applies:
|
||||||
|
Copyright 2007 Yusuke Yamamoto
|
||||||
|
|
||||||
|
Twitter4J includes software from JSON.org to parse JSON response from the Twitter API. You can see the license term at http://www.JSON.org/license.html
|
||||||
|
|
||||||
|
(ASLv2) JOAuth
|
||||||
|
The following NOTICE information applies:
|
||||||
|
JOAuth
|
||||||
|
Copyright 2010-2013 Twitter, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
(ASLv2) Hosebird Client
|
||||||
|
The following NOTICE information applies:
|
||||||
|
Hosebird Client (hbc)
|
||||||
|
Copyright 2013 Twitter, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
(ASLv2) GeoIP2 Java API
|
||||||
|
The following NOTICE information applies:
|
||||||
|
GeoIP2 Java API
|
||||||
|
This software is Copyright (c) 2013 by MaxMind, Inc.
|
||||||
|
|
||||||
|
This is free software, licensed under the Apache License, Version 2.0.
|
||||||
|
|
||||||
|
(ASLv2) Google HTTP Client Library for Java
|
||||||
|
The following NOTICE information applies:
|
||||||
|
Google HTTP Client Library for Java
|
||||||
|
|
||||||
|
This is free software, licensed under the Apache License, Version 2.0.
|
||||||
|
|
||||||
|
(ASLv2) Amazon Web Services SDK
|
||||||
|
The following NOTICE information applies:
|
||||||
|
Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
|
This product includes software developed by
|
||||||
|
Amazon Technologies, Inc (http://www.amazon.com/).
|
||||||
|
|
||||||
|
**********************
|
||||||
|
THIRD PARTY COMPONENTS
|
||||||
|
**********************
|
||||||
|
This software includes third party software subject to the following copyrights:
|
||||||
|
- XML parsing and utility functions from JetS3t - Copyright 2006-2009 James Murty.
|
||||||
|
- JSON parsing and utility functions from JSON.org - Copyright 2002 JSON.org.
|
||||||
|
- PKCS#1 PEM encoded private key parsing and utility functions from oauth.googlecode.com - Copyright 1998-2010 AOL Inc.
|
||||||
|
|
||||||
|
|
||||||
************************
|
************************
|
||||||
Common Development and Distribution License 1.1
|
Common Development and Distribution License 1.1
|
||||||
|
@ -540,6 +588,14 @@ The following binary components are provided under the Common Development and Di
|
||||||
(CDDL 1.0) JavaServer Pages(TM) API (javax.servlet.jsp:jsp-api:jar:2.1 - http://jsp.java.net)
|
(CDDL 1.0) JavaServer Pages(TM) API (javax.servlet.jsp:jsp-api:jar:2.1 - http://jsp.java.net)
|
||||||
(CDDL 1.0) SR 250 Common Annotations For The JavaTM Platform (javax.annotation:jsr250-api:jar:1.0 - http://jcp.org/aboutJava/communityprocess/final/jsr250/index.html)
|
(CDDL 1.0) SR 250 Common Annotations For The JavaTM Platform (javax.annotation:jsr250-api:jar:1.0 - http://jcp.org/aboutJava/communityprocess/final/jsr250/index.html)
|
||||||
|
|
||||||
|
************************
|
||||||
|
Creative Commons Attribution-ShareAlike 3.0
|
||||||
|
************************
|
||||||
|
|
||||||
|
The following binary components are provided under the Creative Commons Attribution-ShareAlike 3.0. See project link for details.
|
||||||
|
|
||||||
|
(CCAS 3.0) MaxMind DB (https://github.com/maxmind/MaxMind-DB)
|
||||||
|
|
||||||
************************
|
************************
|
||||||
Eclipse Public License 1.0
|
Eclipse Public License 1.0
|
||||||
************************
|
************************
|
||||||
|
@ -559,6 +615,15 @@ The following binary components are provided under the Mozilla Public License v2
|
||||||
|
|
||||||
(MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:9.6.0-4 - http://www.saxonica.com/)
|
(MPL 2.0) Saxon HE (net.sf.saxon:Saxon-HE:jar:9.6.0-4 - http://www.saxonica.com/)
|
||||||
|
|
||||||
|
*****************
|
||||||
|
Mozilla Public License v1.1
|
||||||
|
*****************
|
||||||
|
|
||||||
|
The following binary components are provided under the Mozilla Public License v1.1. See project link for details.
|
||||||
|
|
||||||
|
(MPL 1.1) HAPI Base (ca.uhn.hapi:hapi-base:2.2 - http://hl7api.sourceforge.net/)
|
||||||
|
(MPL 1.1) HAPI Structures (ca.uhn.hapi:hapi-structures-v*:2.2 - http://hl7api.sourceforge.net/)
|
||||||
|
|
||||||
*****************
|
*****************
|
||||||
Public Domain
|
Public Domain
|
||||||
*****************
|
*****************
|
||||||
|
|
|
@ -1,462 +1,489 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
license agreements. See the NOTICE file distributed with this work for additional
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
information regarding copyright ownership. The ASF licenses this file to
|
||||||
this work for additional information regarding copyright ownership.
|
You under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
this file except in compliance with the License. You may obtain a copy of
|
||||||
(the "License"); you may not use this file except in compliance with
|
the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
|
||||||
the License. You may obtain a copy of the License at
|
by applicable law or agreed to in writing, software distributed under the
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||||
Unless required by applicable law or agreed to in writing, software
|
OF ANY KIND, either express or implied. See the License for the specific
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
language governing permissions and limitations under the License. -->
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
See the License for the specific language governing permissions and
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
limitations under the License.
|
<modelVersion>4.0.0</modelVersion>
|
||||||
-->
|
<parent>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<groupId>org.apache.nifi</groupId>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<artifactId>nifi</artifactId>
|
||||||
<parent>
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
<groupId>org.apache.nifi</groupId>
|
</parent>
|
||||||
<artifactId>nifi</artifactId>
|
<artifactId>nifi-assembly</artifactId>
|
||||||
<version>0.1.0-incubating-SNAPSHOT</version>
|
<packaging>pom</packaging>
|
||||||
</parent>
|
<description>This is the assembly Apache NiFi (incubating)</description>
|
||||||
<artifactId>nifi-assembly</artifactId>
|
<build>
|
||||||
<packaging>pom</packaging>
|
<plugins>
|
||||||
<description>This is the assembly Apache NiFi (incubating)</description>
|
<plugin>
|
||||||
<build>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<plugins>
|
<configuration>
|
||||||
<plugin>
|
<finalName>nifi-${project.version}</finalName>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<attach>false</attach>
|
||||||
<configuration>
|
</configuration>
|
||||||
<finalName>nifi-${project.version}</finalName>
|
<executions>
|
||||||
<attach>false</attach>
|
<execution>
|
||||||
</configuration>
|
<id>make shared resource</id>
|
||||||
<executions>
|
<goals>
|
||||||
<execution>
|
<goal>single</goal>
|
||||||
<id>make shared resource</id>
|
</goals>
|
||||||
<goals>
|
<phase>package</phase>
|
||||||
<goal>single</goal>
|
<configuration>
|
||||||
</goals>
|
<descriptors>
|
||||||
<phase>package</phase>
|
<descriptor>src/main/assembly/dependencies.xml</descriptor>
|
||||||
<configuration>
|
</descriptors>
|
||||||
<descriptors>
|
<tarLongFileMode>posix</tarLongFileMode>
|
||||||
<descriptor>src/main/assembly/dependencies.xml</descriptor>
|
</configuration>
|
||||||
</descriptors>
|
</execution>
|
||||||
<tarLongFileMode>posix</tarLongFileMode>
|
</executions>
|
||||||
</configuration>
|
</plugin>
|
||||||
</execution>
|
</plugins>
|
||||||
</executions>
|
</build>
|
||||||
</plugin>
|
<dependencies>
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-classic</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>jul-to-slf4j</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>log4j-over-slf4j</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-runtime</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-bootstrap</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-resources</artifactId>
|
|
||||||
<classifier>resources</classifier>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
<type>zip</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-docs</artifactId>
|
|
||||||
<classifier>resources</classifier>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
<type>zip</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-framework-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-provenance-repository-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-standard-services-api-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-ssl-context-service-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-distributed-cache-services-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-standard-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-jetty-bundle</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-update-attribute-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-hadoop-libraries-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-hadoop-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.nifi</groupId>
|
|
||||||
<artifactId>nifi-kafka-nar</artifactId>
|
|
||||||
<type>nar</type>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>nifi-http-context-map-nar</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<type>nar</type>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>nifi-kite-nar</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<type>nar</type>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>jul-to-slf4j</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>log4j-over-slf4j</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-runtime</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-bootstrap</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-resources</artifactId>
|
||||||
|
<classifier>resources</classifier>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<type>zip</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-docs</artifactId>
|
||||||
|
<classifier>resources</classifier>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<type>zip</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-framework-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-provenance-repository-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-standard-services-api-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-ssl-context-service-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-distributed-cache-services-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-standard-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-jetty-bundle</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-update-attribute-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-hadoop-libraries-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-hadoop-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-kafka-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-http-context-map-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-kite-nar</artifactId>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.apache.nifi</groupId>
|
||||||
<artifactId>nifi-solr-nar</artifactId>
|
<artifactId>nifi-solr-nar</artifactId>
|
||||||
<type>nar</type>
|
<type>nar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-social-media-nar</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-hl7-nar</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-language-translation-nar</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-geo-nar</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!--Wrapper Properties-->
|
<!--Wrapper Properties -->
|
||||||
<nifi.wrapper.jvm.heap.initial.mb>256</nifi.wrapper.jvm.heap.initial.mb>
|
<nifi.wrapper.jvm.heap.initial.mb>256</nifi.wrapper.jvm.heap.initial.mb>
|
||||||
<nifi.wrapper.jvm.heap.max.mb>512</nifi.wrapper.jvm.heap.max.mb>
|
<nifi.wrapper.jvm.heap.max.mb>512</nifi.wrapper.jvm.heap.max.mb>
|
||||||
<nifi.initial.permgen.size.mb>128</nifi.initial.permgen.size.mb>
|
<nifi.initial.permgen.size.mb>128</nifi.initial.permgen.size.mb>
|
||||||
<nifi.max.permgen.size.mb>128</nifi.max.permgen.size.mb>
|
<nifi.max.permgen.size.mb>128</nifi.max.permgen.size.mb>
|
||||||
<nifi.wrapper.logfile.maxsize>10m</nifi.wrapper.logfile.maxsize>
|
<nifi.wrapper.logfile.maxsize>10m</nifi.wrapper.logfile.maxsize>
|
||||||
<nifi.wrapper.logfile.maxfiles>10</nifi.wrapper.logfile.maxfiles>
|
<nifi.wrapper.logfile.maxfiles>10</nifi.wrapper.logfile.maxfiles>
|
||||||
|
|
||||||
<!-- nifi.properties: core properties -->
|
<!-- nifi.properties: core properties -->
|
||||||
<nifi.version>${project.version}</nifi.version>
|
<nifi.version>${project.version}</nifi.version>
|
||||||
<nifi.flowcontroller.autoResumeState>true</nifi.flowcontroller.autoResumeState>
|
<nifi.flowcontroller.autoResumeState>true</nifi.flowcontroller.autoResumeState>
|
||||||
<nifi.flowcontroller.graceful.shutdown.period>10 sec</nifi.flowcontroller.graceful.shutdown.period>
|
<nifi.flowcontroller.graceful.shutdown.period>10 sec</nifi.flowcontroller.graceful.shutdown.period>
|
||||||
<nifi.flowservice.writedelay.interval>500 ms</nifi.flowservice.writedelay.interval>
|
<nifi.flowservice.writedelay.interval>500 ms</nifi.flowservice.writedelay.interval>
|
||||||
<nifi.administrative.yield.duration>30 sec</nifi.administrative.yield.duration>
|
<nifi.administrative.yield.duration>30 sec</nifi.administrative.yield.duration>
|
||||||
<nifi.bored.yield.duration>10 millis</nifi.bored.yield.duration>
|
<nifi.bored.yield.duration>10 millis</nifi.bored.yield.duration>
|
||||||
|
|
||||||
<nifi.flow.configuration.file>./conf/flow.xml.gz</nifi.flow.configuration.file>
|
<nifi.flow.configuration.file>./conf/flow.xml.gz</nifi.flow.configuration.file>
|
||||||
<nifi.flow.configuration.archive.dir>./conf/archive/</nifi.flow.configuration.archive.dir>
|
<nifi.flow.configuration.archive.dir>./conf/archive/</nifi.flow.configuration.archive.dir>
|
||||||
<nifi.authority.provider.configuration.file>./conf/authority-providers.xml</nifi.authority.provider.configuration.file>
|
<nifi.authority.provider.configuration.file>./conf/authority-providers.xml</nifi.authority.provider.configuration.file>
|
||||||
<nifi.templates.directory>./conf/templates</nifi.templates.directory>
|
<nifi.templates.directory>./conf/templates</nifi.templates.directory>
|
||||||
<nifi.database.directory>./database_repository</nifi.database.directory>
|
<nifi.database.directory>./database_repository</nifi.database.directory>
|
||||||
|
|
||||||
<nifi.flowfile.repository.implementation>org.apache.nifi.controller.repository.WriteAheadFlowFileRepository</nifi.flowfile.repository.implementation>
|
<nifi.flowfile.repository.implementation>org.apache.nifi.controller.repository.WriteAheadFlowFileRepository</nifi.flowfile.repository.implementation>
|
||||||
<nifi.flowfile.repository.directory>./flowfile_repository</nifi.flowfile.repository.directory>
|
<nifi.flowfile.repository.directory>./flowfile_repository</nifi.flowfile.repository.directory>
|
||||||
<nifi.flowfile.repository.partitions>256</nifi.flowfile.repository.partitions>
|
<nifi.flowfile.repository.partitions>256</nifi.flowfile.repository.partitions>
|
||||||
<nifi.flowfile.repository.checkpoint.interval>2 mins</nifi.flowfile.repository.checkpoint.interval>
|
<nifi.flowfile.repository.checkpoint.interval>2 mins</nifi.flowfile.repository.checkpoint.interval>
|
||||||
<nifi.flowfile.repository.always.sync>false</nifi.flowfile.repository.always.sync>
|
<nifi.flowfile.repository.always.sync>false</nifi.flowfile.repository.always.sync>
|
||||||
<nifi.swap.manager.implementation>org.apache.nifi.controller.FileSystemSwapManager</nifi.swap.manager.implementation>
|
<nifi.swap.manager.implementation>org.apache.nifi.controller.FileSystemSwapManager</nifi.swap.manager.implementation>
|
||||||
<nifi.queue.swap.threshold>20000</nifi.queue.swap.threshold>
|
<nifi.queue.swap.threshold>20000</nifi.queue.swap.threshold>
|
||||||
<nifi.swap.in.period>5 sec</nifi.swap.in.period>
|
<nifi.swap.in.period>5 sec</nifi.swap.in.period>
|
||||||
<nifi.swap.in.threads>1</nifi.swap.in.threads>
|
<nifi.swap.in.threads>1</nifi.swap.in.threads>
|
||||||
<nifi.swap.out.period>5 sec</nifi.swap.out.period>
|
<nifi.swap.out.period>5 sec</nifi.swap.out.period>
|
||||||
<nifi.swap.out.threads>4</nifi.swap.out.threads>
|
<nifi.swap.out.threads>4</nifi.swap.out.threads>
|
||||||
|
|
||||||
<nifi.content.repository.implementation>org.apache.nifi.controller.repository.FileSystemRepository</nifi.content.repository.implementation>
|
<nifi.content.repository.implementation>org.apache.nifi.controller.repository.FileSystemRepository</nifi.content.repository.implementation>
|
||||||
<nifi.content.claim.max.appendable.size>10 MB</nifi.content.claim.max.appendable.size>
|
<nifi.content.claim.max.appendable.size>10 MB</nifi.content.claim.max.appendable.size>
|
||||||
<nifi.content.claim.max.flow.files>100</nifi.content.claim.max.flow.files>
|
<nifi.content.claim.max.flow.files>100</nifi.content.claim.max.flow.files>
|
||||||
<nifi.content.repository.directory.default>./content_repository</nifi.content.repository.directory.default>
|
<nifi.content.repository.directory.default>./content_repository</nifi.content.repository.directory.default>
|
||||||
<nifi.content.repository.archive.max.retention.period />
|
<nifi.content.repository.archive.max.retention.period />
|
||||||
<nifi.content.repository.archive.max.usage.percentage />
|
<nifi.content.repository.archive.max.usage.percentage />
|
||||||
<nifi.content.repository.archive.enabled>false</nifi.content.repository.archive.enabled>
|
<nifi.content.repository.archive.enabled>false</nifi.content.repository.archive.enabled>
|
||||||
<nifi.content.repository.always.sync>false</nifi.content.repository.always.sync>
|
<nifi.content.repository.always.sync>false</nifi.content.repository.always.sync>
|
||||||
<nifi.content.viewer.url />
|
<nifi.content.viewer.url />
|
||||||
|
|
||||||
<nifi.restore.directory />
|
<nifi.restore.directory />
|
||||||
<nifi.ui.banner.text />
|
<nifi.ui.banner.text />
|
||||||
<nifi.ui.autorefresh.interval>30 sec</nifi.ui.autorefresh.interval>
|
<nifi.ui.autorefresh.interval>30 sec</nifi.ui.autorefresh.interval>
|
||||||
<nifi.nar.library.directory>./lib</nifi.nar.library.directory>
|
<nifi.nar.library.directory>./lib</nifi.nar.library.directory>
|
||||||
<nifi.nar.working.directory>./work/nar/</nifi.nar.working.directory>
|
<nifi.nar.working.directory>./work/nar/</nifi.nar.working.directory>
|
||||||
<nifi.documentation.working.directory>./work/docs/components</nifi.documentation.working.directory>
|
<nifi.documentation.working.directory>./work/docs/components</nifi.documentation.working.directory>
|
||||||
|
|
||||||
<nifi.sensitive.props.algorithm>PBEWITHMD5AND256BITAES-CBC-OPENSSL</nifi.sensitive.props.algorithm>
|
<nifi.sensitive.props.algorithm>PBEWITHMD5AND256BITAES-CBC-OPENSSL</nifi.sensitive.props.algorithm>
|
||||||
<nifi.sensitive.props.provider>BC</nifi.sensitive.props.provider>
|
<nifi.sensitive.props.provider>BC</nifi.sensitive.props.provider>
|
||||||
<nifi.h2.url.append>;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE</nifi.h2.url.append>
|
<nifi.h2.url.append>;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE</nifi.h2.url.append>
|
||||||
|
|
||||||
<nifi.remote.input.socket.port>9990</nifi.remote.input.socket.port>
|
<nifi.remote.input.socket.port>9990</nifi.remote.input.socket.port>
|
||||||
|
|
||||||
<!-- persistent provenance repository properties -->
|
<!-- persistent provenance repository properties -->
|
||||||
<nifi.provenance.repository.implementation>org.apache.nifi.provenance.PersistentProvenanceRepository</nifi.provenance.repository.implementation>
|
<nifi.provenance.repository.implementation>org.apache.nifi.provenance.PersistentProvenanceRepository</nifi.provenance.repository.implementation>
|
||||||
<nifi.provenance.repository.directory.default>./provenance_repository</nifi.provenance.repository.directory.default>
|
<nifi.provenance.repository.directory.default>./provenance_repository</nifi.provenance.repository.directory.default>
|
||||||
<nifi.provenance.repository.max.storage.time>24 hours</nifi.provenance.repository.max.storage.time>
|
<nifi.provenance.repository.max.storage.time>24 hours</nifi.provenance.repository.max.storage.time>
|
||||||
<nifi.provenance.repository.max.storage.size>1 GB</nifi.provenance.repository.max.storage.size>
|
<nifi.provenance.repository.max.storage.size>1 GB</nifi.provenance.repository.max.storage.size>
|
||||||
<nifi.provenance.repository.rollover.time>5 mins</nifi.provenance.repository.rollover.time>
|
<nifi.provenance.repository.rollover.time>5 mins</nifi.provenance.repository.rollover.time>
|
||||||
<nifi.provenance.repository.rollover.size>100 MB</nifi.provenance.repository.rollover.size>
|
<nifi.provenance.repository.rollover.size>100 MB</nifi.provenance.repository.rollover.size>
|
||||||
<nifi.provenance.repository.query.threads>2</nifi.provenance.repository.query.threads>
|
<nifi.provenance.repository.query.threads>2</nifi.provenance.repository.query.threads>
|
||||||
<nifi.provenance.repository.compress.on.rollover>true</nifi.provenance.repository.compress.on.rollover>
|
<nifi.provenance.repository.compress.on.rollover>true</nifi.provenance.repository.compress.on.rollover>
|
||||||
<nifi.provenance.repository.indexed.fields>EventType, FlowFileUUID, Filename, ProcessorID</nifi.provenance.repository.indexed.fields>
|
<nifi.provenance.repository.indexed.fields>EventType, FlowFileUUID,
|
||||||
<nifi.provenance.repository.indexed.attributes />
|
Filename, ProcessorID</nifi.provenance.repository.indexed.fields>
|
||||||
<nifi.provenance.repository.index.shard.size>500 MB</nifi.provenance.repository.index.shard.size>
|
<nifi.provenance.repository.indexed.attributes />
|
||||||
<nifi.provenance.repository.always.sync>false</nifi.provenance.repository.always.sync>
|
<nifi.provenance.repository.index.shard.size>500 MB</nifi.provenance.repository.index.shard.size>
|
||||||
<nifi.provenance.repository.journal.count>16</nifi.provenance.repository.journal.count>
|
<nifi.provenance.repository.always.sync>false</nifi.provenance.repository.always.sync>
|
||||||
|
<nifi.provenance.repository.journal.count>16</nifi.provenance.repository.journal.count>
|
||||||
|
|
||||||
<!-- volatile provenance repository properties -->
|
<!-- volatile provenance repository properties -->
|
||||||
<nifi.provenance.repository.buffer.size>100000</nifi.provenance.repository.buffer.size>
|
<nifi.provenance.repository.buffer.size>100000</nifi.provenance.repository.buffer.size>
|
||||||
|
|
||||||
<!-- Component status repository properties -->
|
<!-- Component status repository properties -->
|
||||||
<nifi.components.status.repository.implementation>org.apache.nifi.controller.status.history.VolatileComponentStatusRepository</nifi.components.status.repository.implementation>
|
<nifi.components.status.repository.implementation>org.apache.nifi.controller.status.history.VolatileComponentStatusRepository</nifi.components.status.repository.implementation>
|
||||||
<nifi.components.status.repository.buffer.size>288</nifi.components.status.repository.buffer.size>
|
<nifi.components.status.repository.buffer.size>288</nifi.components.status.repository.buffer.size>
|
||||||
<nifi.components.status.snapshot.frequency>5 mins</nifi.components.status.snapshot.frequency>
|
<nifi.components.status.snapshot.frequency>5 mins</nifi.components.status.snapshot.frequency>
|
||||||
|
|
||||||
<!-- nifi.properties: web properties -->
|
<!-- nifi.properties: web properties -->
|
||||||
<nifi.web.war.directory>./lib</nifi.web.war.directory>
|
<nifi.web.war.directory>./lib</nifi.web.war.directory>
|
||||||
<nifi.web.http.host />
|
<nifi.web.http.host />
|
||||||
<nifi.web.http.port>8080</nifi.web.http.port>
|
<nifi.web.http.port>8080</nifi.web.http.port>
|
||||||
<nifi.web.https.host />
|
<nifi.web.https.host />
|
||||||
<nifi.web.https.port />
|
<nifi.web.https.port />
|
||||||
<nifi.jetty.work.dir>./work/jetty</nifi.jetty.work.dir>
|
<nifi.jetty.work.dir>./work/jetty</nifi.jetty.work.dir>
|
||||||
<nifi.web.jetty.threads>200</nifi.web.jetty.threads>
|
<nifi.web.jetty.threads>200</nifi.web.jetty.threads>
|
||||||
|
|
||||||
<!-- nifi.properties: security properties -->
|
<!-- nifi.properties: security properties -->
|
||||||
<nifi.security.keystore />
|
<nifi.security.keystore />
|
||||||
<nifi.security.keystoreType />
|
<nifi.security.keystoreType />
|
||||||
<nifi.security.keystorePasswd />
|
<nifi.security.keystorePasswd />
|
||||||
<nifi.security.keyPasswd />
|
<nifi.security.keyPasswd />
|
||||||
<nifi.security.truststore />
|
<nifi.security.truststore />
|
||||||
<nifi.security.truststoreType />
|
<nifi.security.truststoreType />
|
||||||
<nifi.security.truststorePasswd />
|
<nifi.security.truststorePasswd />
|
||||||
<nifi.security.needClientAuth />
|
<nifi.security.needClientAuth />
|
||||||
<nifi.security.authorizedUsers.file>./conf/authorized-users.xml</nifi.security.authorizedUsers.file>
|
<nifi.security.authorizedUsers.file>./conf/authorized-users.xml</nifi.security.authorizedUsers.file>
|
||||||
<nifi.security.user.credential.cache.duration>24 hours</nifi.security.user.credential.cache.duration>
|
<nifi.security.user.credential.cache.duration>24 hours</nifi.security.user.credential.cache.duration>
|
||||||
<nifi.security.user.authority.provider>file-provider</nifi.security.user.authority.provider>
|
<nifi.security.user.authority.provider>file-provider</nifi.security.user.authority.provider>
|
||||||
<nifi.security.x509.principal.extractor />
|
<nifi.security.x509.principal.extractor />
|
||||||
<nifi.security.support.new.account.requests />
|
<nifi.security.support.new.account.requests />
|
||||||
<nifi.security.ocsp.responder.url />
|
<nifi.security.ocsp.responder.url />
|
||||||
<nifi.security.ocsp.responder.certificate />
|
<nifi.security.ocsp.responder.certificate />
|
||||||
|
|
||||||
<!-- nifi.properties: cluster common properties (cluster manager and nodes must have same values) -->
|
<!-- nifi.properties: cluster common properties (cluster manager and nodes
|
||||||
<nifi.cluster.protocol.heartbeat.interval>5 sec</nifi.cluster.protocol.heartbeat.interval>
|
must have same values) -->
|
||||||
<nifi.cluster.protocol.is.secure>false</nifi.cluster.protocol.is.secure>
|
<nifi.cluster.protocol.heartbeat.interval>5 sec</nifi.cluster.protocol.heartbeat.interval>
|
||||||
<nifi.cluster.protocol.socket.timeout>30 sec</nifi.cluster.protocol.socket.timeout>
|
<nifi.cluster.protocol.is.secure>false</nifi.cluster.protocol.is.secure>
|
||||||
<nifi.cluster.protocol.connection.handshake.timeout>45 sec</nifi.cluster.protocol.connection.handshake.timeout>
|
<nifi.cluster.protocol.socket.timeout>30 sec</nifi.cluster.protocol.socket.timeout>
|
||||||
<nifi.cluster.protocol.use.multicast>false</nifi.cluster.protocol.use.multicast>
|
<nifi.cluster.protocol.connection.handshake.timeout>45 sec</nifi.cluster.protocol.connection.handshake.timeout>
|
||||||
<nifi.cluster.protocol.multicast.address />
|
<nifi.cluster.protocol.use.multicast>false</nifi.cluster.protocol.use.multicast>
|
||||||
<nifi.cluster.protocol.multicast.port />
|
<nifi.cluster.protocol.multicast.address />
|
||||||
<nifi.cluster.protocol.multicast.service.broadcast.delay>500 ms</nifi.cluster.protocol.multicast.service.broadcast.delay>
|
<nifi.cluster.protocol.multicast.port />
|
||||||
<nifi.cluster.protocol.multicast.service.locator.attempts>3</nifi.cluster.protocol.multicast.service.locator.attempts>
|
<nifi.cluster.protocol.multicast.service.broadcast.delay>500 ms</nifi.cluster.protocol.multicast.service.broadcast.delay>
|
||||||
<nifi.cluster.protocol.multicast.service.locator.attempts.delay>1 sec</nifi.cluster.protocol.multicast.service.locator.attempts.delay>
|
<nifi.cluster.protocol.multicast.service.locator.attempts>3</nifi.cluster.protocol.multicast.service.locator.attempts>
|
||||||
|
<nifi.cluster.protocol.multicast.service.locator.attempts.delay>1 sec</nifi.cluster.protocol.multicast.service.locator.attempts.delay>
|
||||||
|
|
||||||
<!-- nifi.properties: cluster node properties (only configure for cluster nodes) -->
|
<!-- nifi.properties: cluster node properties (only configure for cluster
|
||||||
<nifi.cluster.is.node>false</nifi.cluster.is.node>
|
nodes) -->
|
||||||
<nifi.cluster.node.address />
|
<nifi.cluster.is.node>false</nifi.cluster.is.node>
|
||||||
<nifi.cluster.node.protocol.port />
|
<nifi.cluster.node.address />
|
||||||
<nifi.cluster.node.protocol.threads>2</nifi.cluster.node.protocol.threads>
|
<nifi.cluster.node.protocol.port />
|
||||||
<nifi.cluster.node.unicast.manager.address />
|
<nifi.cluster.node.protocol.threads>2</nifi.cluster.node.protocol.threads>
|
||||||
<nifi.cluster.node.unicast.manager.protocol.port />
|
<nifi.cluster.node.unicast.manager.address />
|
||||||
|
<nifi.cluster.node.unicast.manager.protocol.port />
|
||||||
|
|
||||||
<!-- nifi.properties: cluster manager properties (only configure for cluster manager) -->
|
<!-- nifi.properties: cluster manager properties (only configure for cluster
|
||||||
<nifi.cluster.is.manager>false</nifi.cluster.is.manager>
|
manager) -->
|
||||||
<nifi.cluster.manager.address />
|
<nifi.cluster.is.manager>false</nifi.cluster.is.manager>
|
||||||
<nifi.cluster.manager.protocol.port />
|
<nifi.cluster.manager.address />
|
||||||
<nifi.cluster.manager.node.firewall.file />
|
<nifi.cluster.manager.protocol.port />
|
||||||
<nifi.cluster.manager.node.event.history.size>10</nifi.cluster.manager.node.event.history.size>
|
<nifi.cluster.manager.node.firewall.file />
|
||||||
<nifi.cluster.manager.node.api.connection.timeout>30 sec</nifi.cluster.manager.node.api.connection.timeout>
|
<nifi.cluster.manager.node.event.history.size>10</nifi.cluster.manager.node.event.history.size>
|
||||||
<nifi.cluster.manager.node.api.read.timeout>30 sec</nifi.cluster.manager.node.api.read.timeout>
|
<nifi.cluster.manager.node.api.connection.timeout>30 sec</nifi.cluster.manager.node.api.connection.timeout>
|
||||||
<nifi.cluster.manager.node.api.request.threads>10</nifi.cluster.manager.node.api.request.threads>
|
<nifi.cluster.manager.node.api.read.timeout>30 sec</nifi.cluster.manager.node.api.read.timeout>
|
||||||
<nifi.cluster.manager.flow.retrieval.delay>5 sec</nifi.cluster.manager.flow.retrieval.delay>
|
<nifi.cluster.manager.node.api.request.threads>10</nifi.cluster.manager.node.api.request.threads>
|
||||||
<nifi.cluster.manager.protocol.threads>10</nifi.cluster.manager.protocol.threads>
|
<nifi.cluster.manager.flow.retrieval.delay>5 sec</nifi.cluster.manager.flow.retrieval.delay>
|
||||||
<nifi.cluster.manager.safemode.duration>0 sec</nifi.cluster.manager.safemode.duration>
|
<nifi.cluster.manager.protocol.threads>10</nifi.cluster.manager.protocol.threads>
|
||||||
</properties>
|
<nifi.cluster.manager.safemode.duration>0 sec</nifi.cluster.manager.safemode.duration>
|
||||||
<profiles>
|
</properties>
|
||||||
<profile>
|
<profiles>
|
||||||
<id>rpm</id>
|
<profile>
|
||||||
<activation>
|
<id>rpm</id>
|
||||||
<activeByDefault>false</activeByDefault>
|
<activation>
|
||||||
</activation>
|
<activeByDefault>false</activeByDefault>
|
||||||
<build>
|
</activation>
|
||||||
<plugins>
|
<build>
|
||||||
<plugin>
|
<plugins>
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
<plugin>
|
||||||
<executions>
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
<execution>
|
<executions>
|
||||||
<id>unpack-shared-resources</id>
|
<execution>
|
||||||
<goals>
|
<id>unpack-shared-resources</id>
|
||||||
<goal>unpack-dependencies</goal>
|
<goals>
|
||||||
</goals>
|
<goal>unpack-dependencies</goal>
|
||||||
<phase>generate-resources</phase>
|
</goals>
|
||||||
<configuration>
|
<phase>generate-resources</phase>
|
||||||
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
|
<configuration>
|
||||||
<includeArtifactIds>nifi-resources</includeArtifactIds>
|
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
|
||||||
<includeGroupIds>org.apache.nifi</includeGroupIds>
|
<includeArtifactIds>nifi-resources</includeArtifactIds>
|
||||||
<excludeTransitive>false</excludeTransitive>
|
<includeGroupIds>org.apache.nifi</includeGroupIds>
|
||||||
</configuration>
|
<excludeTransitive>false</excludeTransitive>
|
||||||
</execution>
|
</configuration>
|
||||||
<execution>
|
</execution>
|
||||||
<id>unpack-docs</id>
|
<execution>
|
||||||
<goals>
|
<id>unpack-docs</id>
|
||||||
<goal>unpack-dependencies</goal>
|
<goals>
|
||||||
</goals>
|
<goal>unpack-dependencies</goal>
|
||||||
<phase>generate-resources</phase>
|
</goals>
|
||||||
<configuration>
|
<phase>generate-resources</phase>
|
||||||
<outputDirectory>${project.build.directory}/generated-docs</outputDirectory>
|
<configuration>
|
||||||
<includeArtifactIds>nifi-docs</includeArtifactIds>
|
<outputDirectory>${project.build.directory}/generated-docs</outputDirectory>
|
||||||
<includeGroupIds>org.apache.nifi</includeGroupIds>
|
<includeArtifactIds>nifi-docs</includeArtifactIds>
|
||||||
<excludeTransitive>false</excludeTransitive>
|
<includeGroupIds>org.apache.nifi</includeGroupIds>
|
||||||
</configuration>
|
<excludeTransitive>false</excludeTransitive>
|
||||||
</execution>
|
</configuration>
|
||||||
</executions>
|
</execution>
|
||||||
</plugin>
|
</executions>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<plugin>
|
||||||
<artifactId>rpm-maven-plugin</artifactId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<configuration>
|
<artifactId>rpm-maven-plugin</artifactId>
|
||||||
<summary>Apache NiFi (incubating)</summary>
|
<configuration>
|
||||||
<description>Apache Nifi (incubating) is dataflow system based on the Flow-Based Programming concepts.</description>
|
<summary>Apache NiFi (incubating)</summary>
|
||||||
<license>Apache License, Version 2.0 and others (see included LICENSE file)</license>
|
<description>Apache Nifi (incubating) is dataflow system based on
|
||||||
<url>http://nifi.incubator.apache.org</url>
|
the Flow-Based Programming concepts.</description>
|
||||||
<group>Utilities</group>
|
<license>Apache License, Version 2.0 and others (see included
|
||||||
<prefix>/opt/nifi</prefix>
|
LICENSE file)</license>
|
||||||
<defineStatements>
|
<url>http://nifi.incubator.apache.org</url>
|
||||||
<defineStatement>_use_internal_dependency_generator 0</defineStatement>
|
<group>Utilities</group>
|
||||||
</defineStatements>
|
<prefix>/opt/nifi</prefix>
|
||||||
<defaultDirmode>750</defaultDirmode>
|
<defineStatements>
|
||||||
<defaultFilemode>640</defaultFilemode>
|
<defineStatement>_use_internal_dependency_generator 0</defineStatement>
|
||||||
<defaultUsername>root</defaultUsername>
|
</defineStatements>
|
||||||
<defaultGroupname>root</defaultGroupname>
|
<defaultDirmode>750</defaultDirmode>
|
||||||
</configuration>
|
<defaultFilemode>640</defaultFilemode>
|
||||||
<executions>
|
<defaultUsername>root</defaultUsername>
|
||||||
<execution>
|
<defaultGroupname>root</defaultGroupname>
|
||||||
<id>build-bin-rpm</id>
|
</configuration>
|
||||||
<goals>
|
<executions>
|
||||||
<goal>attached-rpm</goal>
|
<execution>
|
||||||
</goals>
|
<id>build-bin-rpm</id>
|
||||||
<configuration>
|
<goals>
|
||||||
<classifier>bin</classifier>
|
<goal>attached-rpm</goal>
|
||||||
<provides>
|
</goals>
|
||||||
<provide>nifi</provide>
|
<configuration>
|
||||||
</provides>
|
<classifier>bin</classifier>
|
||||||
<mappings>
|
<provides>
|
||||||
<mapping>
|
<provide>nifi</provide>
|
||||||
<directory>/opt/nifi/nifi-${project.version}</directory>
|
</provides>
|
||||||
</mapping>
|
<mappings>
|
||||||
<mapping>
|
<mapping>
|
||||||
<directory>/opt/nifi/nifi-${project.version}</directory>
|
<directory>/opt/nifi/nifi-${project.version}</directory>
|
||||||
<sources>
|
</mapping>
|
||||||
<source>
|
<mapping>
|
||||||
<location>./LICENSE</location>
|
<directory>/opt/nifi/nifi-${project.version}</directory>
|
||||||
</source>
|
<sources>
|
||||||
<source>
|
<source>
|
||||||
<location>./NOTICE</location>
|
<location>./LICENSE</location>
|
||||||
</source>
|
</source>
|
||||||
<source>
|
<source>
|
||||||
<location>../DISCLAIMER</location>
|
<location>./NOTICE</location>
|
||||||
</source>
|
</source>
|
||||||
<source>
|
<source>
|
||||||
<location>./README.md</location>
|
<location>../DISCLAIMER</location>
|
||||||
<destination>README</destination>
|
</source>
|
||||||
</source>
|
<source>
|
||||||
</sources>
|
<location>./README.md</location>
|
||||||
</mapping>
|
<destination>README</destination>
|
||||||
<mapping>
|
</source>
|
||||||
<directory>/opt/nifi/nifi-${project.version}/bin</directory>
|
</sources>
|
||||||
<filemode>750</filemode>
|
</mapping>
|
||||||
<sources>
|
<mapping>
|
||||||
<source>
|
<directory>/opt/nifi/nifi-${project.version}/bin</directory>
|
||||||
<location>${project.build.directory}/generated-resources/bin/nifi.sh</location>
|
<filemode>750</filemode>
|
||||||
<destination>nifi.sh</destination>
|
<sources>
|
||||||
<filter>true</filter>
|
<source>
|
||||||
</source>
|
<location>${project.build.directory}/generated-resources/bin/nifi.sh</location>
|
||||||
</sources>
|
<destination>nifi.sh</destination>
|
||||||
</mapping>
|
<filter>true</filter>
|
||||||
<mapping>
|
</source>
|
||||||
<directory>/opt/nifi/nifi-${project.version}/conf</directory>
|
</sources>
|
||||||
<configuration>true</configuration>
|
</mapping>
|
||||||
<sources>
|
<mapping>
|
||||||
<source>
|
<directory>/opt/nifi/nifi-${project.version}/conf</directory>
|
||||||
<location>${project.build.directory}/generated-resources/conf</location>
|
<configuration>true</configuration>
|
||||||
<filter>true</filter>
|
<sources>
|
||||||
</source>
|
<source>
|
||||||
</sources>
|
<location>${project.build.directory}/generated-resources/conf</location>
|
||||||
</mapping>
|
<filter>true</filter>
|
||||||
<mapping>
|
</source>
|
||||||
<directory>/opt/nifi/nifi-${project.version}/lib</directory>
|
</sources>
|
||||||
<dependency>
|
</mapping>
|
||||||
<excludes>
|
<mapping>
|
||||||
<exclude>org.apache.nifi:nifi-bootstrap</exclude>
|
<directory>/opt/nifi/nifi-${project.version}/lib</directory>
|
||||||
<exclude>org.apache.nifi:nifi-resources</exclude>
|
<dependency>
|
||||||
<exclude>org.apache.nifi:nifi-docs</exclude>
|
<excludes>
|
||||||
</excludes>
|
<exclude>org.apache.nifi:nifi-bootstrap</exclude>
|
||||||
</dependency>
|
<exclude>org.apache.nifi:nifi-resources</exclude>
|
||||||
</mapping>
|
<exclude>org.apache.nifi:nifi-docs</exclude>
|
||||||
<mapping>
|
</excludes>
|
||||||
<directory>/opt/nifi/nifi-${project.version}/lib/bootstrap</directory>
|
</dependency>
|
||||||
<dependency>
|
</mapping>
|
||||||
<includes>
|
<mapping>
|
||||||
<include>org.apache.nifi:nifi-bootstrap</include>
|
<directory>/opt/nifi/nifi-${project.version}/lib/bootstrap</directory>
|
||||||
</includes>
|
<dependency>
|
||||||
</dependency>
|
<includes>
|
||||||
</mapping>
|
<include>org.apache.nifi:nifi-bootstrap</include>
|
||||||
<mapping>
|
</includes>
|
||||||
<directory>/opt/nifi/nifi-${project.version}/docs</directory>
|
</dependency>
|
||||||
<sources>
|
</mapping>
|
||||||
<source>
|
<mapping>
|
||||||
<location>${project.build.directory}/generated-docs</location>
|
<directory>/opt/nifi/nifi-${project.version}/docs</directory>
|
||||||
</source>
|
<sources>
|
||||||
</sources>
|
<source>
|
||||||
</mapping>
|
<location>${project.build.directory}/generated-docs</location>
|
||||||
</mappings>
|
</source>
|
||||||
</configuration>
|
</sources>
|
||||||
</execution>
|
</mapping>
|
||||||
</executions>
|
</mappings>
|
||||||
</plugin>
|
</configuration>
|
||||||
</plugins>
|
</execution>
|
||||||
</build>
|
</executions>
|
||||||
</profile>
|
</plugin>
|
||||||
</profiles>
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
/target/
|
||||||
|
/target/
|
||||||
|
/target/
|
|
@ -0,0 +1,125 @@
|
||||||
|
<?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>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.rat</groupId>
|
||||||
|
<artifactId>apache-rat-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>src/test/resources/hypoglycemia</exclude>
|
||||||
|
<exclude>src/test/resources/hyperglycemia</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</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>
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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' | '.')*
|
||||||
|
);
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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?);
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,310 @@
|
||||||
|
/*
|
||||||
|
* 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.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.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/hypoglycemia"));
|
||||||
|
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/hypoglycemia"));
|
||||||
|
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("SMITH^JOHN", 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/hypoglycemia")));
|
||||||
|
assertTrue( 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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() );
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
MSH|^~\&|XXXXXX||HealthOrg01||||ORU^R01|Q1111111111111111111|P|2.3|
|
||||||
|
PID|||000000001||SMITH^JOHN||19700101|M||||||||||999999999999|123456789|
|
||||||
|
PD1||||1234567890^LAST^FIRST^M^^^^^NPI|
|
||||||
|
OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000100|||||||||1620^Johnson^John^R||||||20150101000100|||M|||||||||||20150101000100|
|
||||||
|
OBX|1|NM|GLU^Glucose Lvl|159|mg/dL|65-99^65^99|H|||F|||20150101000100|
|
|
@ -0,0 +1,5 @@
|
||||||
|
MSH|^~\&|XXXXXX||HealthOrg01||||ORU^R01|Q1111111111111111111|P|2.3|
|
||||||
|
PID|||000000001||SMITH^JOHN||19700101|M||||||||||999999999999|123456789|
|
||||||
|
PD1||||1234567890^LAST^FIRST^M^^^^^NPI|
|
||||||
|
OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000100|||||||||1620^Johnson^John^R||||||20150101000100|||M|||||||||||20150101000100|
|
||||||
|
OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20150101000100|
|
|
@ -88,6 +88,7 @@ import org.apache.nifi.web.api.dto.ControllerDTO;
|
||||||
import org.apache.nifi.web.api.dto.PortDTO;
|
import org.apache.nifi.web.api.dto.PortDTO;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
public class EndpointConnectionPool {
|
public class EndpointConnectionPool {
|
||||||
public static final long PEER_REFRESH_PERIOD = 60000L;
|
public static final long PEER_REFRESH_PERIOD = 60000L;
|
||||||
|
@ -202,6 +203,28 @@ public class EndpointConnectionPool {
|
||||||
}, 5, 5, TimeUnit.SECONDS);
|
}, 5, 5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void warn(final String msg, final Object... args) {
|
||||||
|
logger.warn(msg, args);
|
||||||
|
if ( eventReporter != null ) {
|
||||||
|
eventReporter.reportEvent(Severity.WARNING, "Site-to-Site", MessageFormatter.arrayFormat(msg, args).getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void warn(final String msg, final Throwable t) {
|
||||||
|
logger.warn(msg, t);
|
||||||
|
|
||||||
|
if ( eventReporter != null ) {
|
||||||
|
eventReporter.reportEvent(Severity.WARNING, "Site-to-Site", msg + ": " + t.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void error(final String msg, final Object... args) {
|
||||||
|
logger.error(msg, args);
|
||||||
|
if ( eventReporter != null ) {
|
||||||
|
eventReporter.reportEvent(Severity.ERROR, "Site-to-Site", MessageFormatter.arrayFormat(msg, args).getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String getPortIdentifier(final TransferDirection transferDirection) throws IOException {
|
private String getPortIdentifier(final TransferDirection transferDirection) throws IOException {
|
||||||
if ( remoteDestination.getIdentifier() != null ) {
|
if ( remoteDestination.getIdentifier() != null ) {
|
||||||
return remoteDestination.getIdentifier();
|
return remoteDestination.getIdentifier();
|
||||||
|
@ -271,6 +294,7 @@ public class EndpointConnectionPool {
|
||||||
logger.debug("{} No Connection available for Port {}; creating new Connection", this, portId);
|
logger.debug("{} No Connection available for Port {}; creating new Connection", this, portId);
|
||||||
protocol = new SocketClientProtocol();
|
protocol = new SocketClientProtocol();
|
||||||
protocol.setDestination(new IdEnrichedRemoteDestination(remoteDestination, portId));
|
protocol.setDestination(new IdEnrichedRemoteDestination(remoteDestination, portId));
|
||||||
|
protocol.setEventReporter(eventReporter);
|
||||||
|
|
||||||
final long penalizationMillis = remoteDestination.getYieldPeriod(TimeUnit.MILLISECONDS);
|
final long penalizationMillis = remoteDestination.getYieldPeriod(TimeUnit.MILLISECONDS);
|
||||||
try {
|
try {
|
||||||
|
@ -312,8 +336,15 @@ public class EndpointConnectionPool {
|
||||||
|
|
||||||
// handle error cases
|
// handle error cases
|
||||||
if ( protocol.isDestinationFull() ) {
|
if ( protocol.isDestinationFull() ) {
|
||||||
logger.warn("{} {} indicates that port's destination is full; penalizing peer", this, peer);
|
logger.warn("{} {} indicates that port {}'s destination is full; penalizing peer",
|
||||||
|
this, peer, config.getPortName() == null ? config.getPortIdentifier() : config.getPortName());
|
||||||
|
|
||||||
penalize(peer, penalizationMillis);
|
penalize(peer, penalizationMillis);
|
||||||
|
try {
|
||||||
|
peer.close();
|
||||||
|
} catch (final IOException ioe) {
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else if ( protocol.isPortInvalid() ) {
|
} else if ( protocol.isPortInvalid() ) {
|
||||||
penalize(peer, penalizationMillis);
|
penalize(peer, penalizationMillis);
|
||||||
|
@ -336,7 +367,7 @@ public class EndpointConnectionPool {
|
||||||
cleanup(protocol, peer);
|
cleanup(protocol, peer);
|
||||||
|
|
||||||
final String message = String.format("%s failed to communicate with %s due to %s", this, peer == null ? clusterUrl : peer, e.toString());
|
final String message = String.format("%s failed to communicate with %s due to %s", this, peer == null ? clusterUrl : peer, e.toString());
|
||||||
logger.error(message);
|
error(message);
|
||||||
if ( logger.isDebugEnabled() ) {
|
if ( logger.isDebugEnabled() ) {
|
||||||
logger.error("", e);
|
logger.error("", e);
|
||||||
}
|
}
|
||||||
|
@ -359,6 +390,15 @@ public class EndpointConnectionPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ( connection == null || codec == null || commsSession == null || protocol == null );
|
} while ( connection == null || codec == null || commsSession == null || protocol == null );
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
if ( commsSession != null ) {
|
||||||
|
try {
|
||||||
|
commsSession.close();
|
||||||
|
} catch (final IOException ioe) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw t;
|
||||||
} finally {
|
} finally {
|
||||||
if ( !addBack.isEmpty() ) {
|
if ( !addBack.isEmpty() ) {
|
||||||
connectionQueue.addAll(addBack);
|
connectionQueue.addAll(addBack);
|
||||||
|
@ -449,7 +489,7 @@ public class EndpointConnectionPool {
|
||||||
peerList = createPeerStatusList(direction);
|
peerList = createPeerStatusList(direction);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
final String message = String.format("%s Failed to update list of peers due to %s", this, e.toString());
|
final String message = String.format("%s Failed to update list of peers due to %s", this, e.toString());
|
||||||
logger.warn(message);
|
warn(message);
|
||||||
if ( logger.isDebugEnabled() ) {
|
if ( logger.isDebugEnabled() ) {
|
||||||
logger.warn("", e);
|
logger.warn("", e);
|
||||||
}
|
}
|
||||||
|
@ -489,7 +529,7 @@ public class EndpointConnectionPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPenalized(final PeerStatus peerStatus) {
|
private boolean isPenalized(final PeerStatus peerStatus) {
|
||||||
final Long expirationEnd = peerTimeoutExpirations.get(peerStatus);
|
final Long expirationEnd = peerTimeoutExpirations.get(peerStatus.getPeerDescription());
|
||||||
return (expirationEnd == null ? false : expirationEnd > System.currentTimeMillis() );
|
return (expirationEnd == null ? false : expirationEnd > System.currentTimeMillis() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +613,7 @@ public class EndpointConnectionPool {
|
||||||
clientProtocol.shutdown(peer);
|
clientProtocol.shutdown(peer);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
final String message = String.format("%s Failed to shutdown protocol when updating list of peers due to %s", this, e.toString());
|
final String message = String.format("%s Failed to shutdown protocol when updating list of peers due to %s", this, e.toString());
|
||||||
logger.warn(message);
|
warn(message);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.warn("", e);
|
logger.warn("", e);
|
||||||
}
|
}
|
||||||
|
@ -583,7 +623,7 @@ public class EndpointConnectionPool {
|
||||||
peer.close();
|
peer.close();
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
final String message = String.format("%s Failed to close resources when updating list of peers due to %s", this, e.toString());
|
final String message = String.format("%s Failed to close resources when updating list of peers due to %s", this, e.toString());
|
||||||
logger.warn(message);
|
warn(message);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.warn("", e);
|
logger.warn("", e);
|
||||||
}
|
}
|
||||||
|
@ -608,7 +648,8 @@ public class EndpointConnectionPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
logger.error("Failed to persist list of Peers due to {}; if restarted and peer's NCM is down, may be unable to transfer data until communications with NCM are restored", e.toString(), e);
|
error("Failed to persist list of Peers due to {}; if restarted and peer's NCM is down, may be unable to transfer data until communications with NCM are restored", e.toString());
|
||||||
|
logger.error("", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +845,7 @@ public class EndpointConnectionPool {
|
||||||
peerStatusCache = new PeerStatusCache(statuses);
|
peerStatusCache = new PeerStatusCache(statuses);
|
||||||
logger.info("{} Successfully refreshed Peer Status; remote instance consists of {} peers", this, statuses.size());
|
logger.info("{} Successfully refreshed Peer Status; remote instance consists of {} peers", this, statuses.size());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("{} Unable to refresh Remote Group's peers due to {}", this, e);
|
warn("{} Unable to refresh Remote Group's peers due to {}", this, e);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.warn("", e);
|
logger.warn("", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ public class SocketClient implements SiteToSiteClient {
|
||||||
logger.debug("Unable to resolve port [{}] to an identifier", portName);
|
logger.debug("Unable to resolve port [{}] to an identifier", portName);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Resolved port [{}] to identifier [{}]", portName, portId);
|
logger.debug("Resolved port [{}] to identifier [{}]", portName, portId);
|
||||||
|
this.portIdentifier = portId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return portId;
|
return portId;
|
||||||
|
@ -136,7 +137,7 @@ public class SocketClient implements SiteToSiteClient {
|
||||||
connectionState.getPeer(), connectionState.getCodec(), direction);
|
connectionState.getPeer(), connectionState.getCodec(), direction);
|
||||||
} catch (final Throwable t) {
|
} catch (final Throwable t) {
|
||||||
pool.terminate(connectionState);
|
pool.terminate(connectionState);
|
||||||
throw t;
|
throw new IOException("Unable to create Transaction to communicate with " + connectionState.getPeer(), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the transaction in a new one that will return the EndpointConnectionState back to the pool whenever
|
// Wrap the transaction in a new one that will return the EndpointConnectionState back to the pool whenever
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.nifi.events.EventReporter;
|
||||||
import org.apache.nifi.flowfile.FlowFile;
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
||||||
import org.apache.nifi.processor.ProcessContext;
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
@ -75,6 +76,7 @@ public class SocketClientProtocol implements ClientProtocol {
|
||||||
private int batchCount;
|
private int batchCount;
|
||||||
private long batchSize;
|
private long batchSize;
|
||||||
private long batchMillis;
|
private long batchMillis;
|
||||||
|
private EventReporter eventReporter;
|
||||||
|
|
||||||
private static final long BATCH_SEND_NANOS = TimeUnit.SECONDS.toNanos(5L); // send batches of up to 5 seconds
|
private static final long BATCH_SEND_NANOS = TimeUnit.SECONDS.toNanos(5L); // send batches of up to 5 seconds
|
||||||
|
|
||||||
|
@ -93,6 +95,10 @@ public class SocketClientProtocol implements ClientProtocol {
|
||||||
this.batchMillis = millis;
|
this.batchMillis = millis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setEventReporter(final EventReporter eventReporter) {
|
||||||
|
this.eventReporter = eventReporter;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDestination(final RemoteDestination destination) {
|
public void setDestination(final RemoteDestination destination) {
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.useCompression = destination.isUseCompression();
|
this.useCompression = destination.isUseCompression();
|
||||||
|
@ -272,7 +278,7 @@ public class SocketClientProtocol implements ClientProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SocketClientTransaction(versionNegotiator.getVersion(), destination.getIdentifier(), peer, codec,
|
return new SocketClientTransaction(versionNegotiator.getVersion(), destination.getIdentifier(), peer, codec,
|
||||||
direction, useCompression, (int) destination.getYieldPeriod(TimeUnit.MILLISECONDS));
|
direction, useCompression, (int) destination.getYieldPeriod(TimeUnit.MILLISECONDS), eventReporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.zip.CRC32;
|
||||||
import java.util.zip.CheckedInputStream;
|
import java.util.zip.CheckedInputStream;
|
||||||
import java.util.zip.CheckedOutputStream;
|
import java.util.zip.CheckedOutputStream;
|
||||||
|
|
||||||
|
import org.apache.nifi.events.EventReporter;
|
||||||
import org.apache.nifi.remote.Communicant;
|
import org.apache.nifi.remote.Communicant;
|
||||||
import org.apache.nifi.remote.Peer;
|
import org.apache.nifi.remote.Peer;
|
||||||
import org.apache.nifi.remote.Transaction;
|
import org.apache.nifi.remote.Transaction;
|
||||||
|
@ -39,6 +40,7 @@ import org.apache.nifi.remote.io.CompressionOutputStream;
|
||||||
import org.apache.nifi.remote.protocol.DataPacket;
|
import org.apache.nifi.remote.protocol.DataPacket;
|
||||||
import org.apache.nifi.remote.protocol.RequestType;
|
import org.apache.nifi.remote.protocol.RequestType;
|
||||||
import org.apache.nifi.remote.util.StandardDataPacket;
|
import org.apache.nifi.remote.util.StandardDataPacket;
|
||||||
|
import org.apache.nifi.reporting.Severity;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
private final Peer peer;
|
private final Peer peer;
|
||||||
private final int penaltyMillis;
|
private final int penaltyMillis;
|
||||||
private final String destinationId;
|
private final String destinationId;
|
||||||
|
private final EventReporter eventReporter;
|
||||||
|
|
||||||
private boolean dataAvailable = false;
|
private boolean dataAvailable = false;
|
||||||
private int transfers = 0;
|
private int transfers = 0;
|
||||||
|
@ -63,7 +66,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
private TransactionState state;
|
private TransactionState state;
|
||||||
|
|
||||||
SocketClientTransaction(final int protocolVersion, final String destinationId, final Peer peer, final FlowFileCodec codec,
|
SocketClientTransaction(final int protocolVersion, final String destinationId, final Peer peer, final FlowFileCodec codec,
|
||||||
final TransferDirection direction, final boolean useCompression, final int penaltyMillis) throws IOException {
|
final TransferDirection direction, final boolean useCompression, final int penaltyMillis, final EventReporter eventReporter) throws IOException {
|
||||||
this.protocolVersion = protocolVersion;
|
this.protocolVersion = protocolVersion;
|
||||||
this.destinationId = destinationId;
|
this.destinationId = destinationId;
|
||||||
this.peer = peer;
|
this.peer = peer;
|
||||||
|
@ -74,6 +77,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
this.compress = useCompression;
|
this.compress = useCompression;
|
||||||
this.state = TransactionState.TRANSACTION_STARTED;
|
this.state = TransactionState.TRANSACTION_STARTED;
|
||||||
this.penaltyMillis = penaltyMillis;
|
this.penaltyMillis = penaltyMillis;
|
||||||
|
this.eventReporter = eventReporter;
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
@ -116,11 +120,11 @@ public class SocketClientTransaction implements Transaction {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if ( state != TransactionState.DATA_EXCHANGED && state != TransactionState.TRANSACTION_STARTED) {
|
if ( state != TransactionState.DATA_EXCHANGED && state != TransactionState.TRANSACTION_STARTED) {
|
||||||
throw new IllegalStateException("Cannot receive data because Transaction State is " + state);
|
throw new IllegalStateException("Cannot receive data from " + peer + " because Transaction State is " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( direction == TransferDirection.SEND ) {
|
if ( direction == TransferDirection.SEND ) {
|
||||||
throw new IllegalStateException("Attempting to receive data but started a SEND Transaction");
|
throw new IllegalStateException("Attempting to receive data from " + peer + " but started a SEND Transaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we already know there's no data, just return null
|
// if we already know there's no data, just return null
|
||||||
|
@ -142,7 +146,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
this.dataAvailable = false;
|
this.dataAvailable = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ProtocolException("Got unexpected response when asking for data: " + dataAvailableCode);
|
throw new ProtocolException("Got unexpected response from " + peer + " when asking for data: " + dataAvailableCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,11 +188,11 @@ public class SocketClientTransaction implements Transaction {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if ( state != TransactionState.DATA_EXCHANGED && state != TransactionState.TRANSACTION_STARTED) {
|
if ( state != TransactionState.DATA_EXCHANGED && state != TransactionState.TRANSACTION_STARTED) {
|
||||||
throw new IllegalStateException("Cannot send data because Transaction State is " + state);
|
throw new IllegalStateException("Cannot send data to " + peer + " because Transaction State is " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( direction == TransferDirection.RECEIVE ) {
|
if ( direction == TransferDirection.RECEIVE ) {
|
||||||
throw new IllegalStateException("Attempting to send data but started a RECEIVE Transaction");
|
throw new IllegalStateException("Attempting to send data to " + peer + " but started a RECEIVE Transaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( transfers > 0 ) {
|
if ( transfers > 0 ) {
|
||||||
|
@ -242,7 +246,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if ( state != TransactionState.TRANSACTION_CONFIRMED ) {
|
if ( state != TransactionState.TRANSACTION_CONFIRMED ) {
|
||||||
throw new IllegalStateException("Cannot complete transaction because state is " + state +
|
throw new IllegalStateException("Cannot complete transaction with " + peer + " because state is " + state +
|
||||||
"; Transaction can only be completed when state is " + TransactionState.TRANSACTION_CONFIRMED);
|
"; Transaction can only be completed when state is " + TransactionState.TRANSACTION_CONFIRMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +276,7 @@ public class SocketClientTransaction implements Transaction {
|
||||||
peer.penalize(destinationId, penaltyMillis);
|
peer.penalize(destinationId, penaltyMillis);
|
||||||
backoff = true;
|
backoff = true;
|
||||||
} else if ( transactionResponse.getCode() != ResponseCode.TRANSACTION_FINISHED ) {
|
} else if ( transactionResponse.getCode() != ResponseCode.TRANSACTION_FINISHED ) {
|
||||||
throw new ProtocolException("After sending data, expected TRANSACTION_FINISHED response but got " + transactionResponse);
|
throw new ProtocolException("After sending data to " + peer + ", expected TRANSACTION_FINISHED response but got " + transactionResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = TransactionState.TRANSACTION_COMPLETED;
|
state = TransactionState.TRANSACTION_COMPLETED;
|
||||||
|
@ -324,7 +328,10 @@ public class SocketClientTransaction implements Transaction {
|
||||||
try {
|
try {
|
||||||
confirmTransactionResponse = Response.read(dis);
|
confirmTransactionResponse = Response.read(dis);
|
||||||
} catch (final IOException ioe) {
|
} catch (final IOException ioe) {
|
||||||
logger.error("Failed to receive response code from {} when expected confirmation of transaction", peer);
|
logger.error("Failed to receive response code from {} when expecting confirmation of transaction", peer);
|
||||||
|
if ( eventReporter != null ) {
|
||||||
|
eventReporter.reportEvent(Severity.ERROR, "Site-to-Site", "Failed to receive response code from " + peer + " when expecting confirmation of transaction");
|
||||||
|
}
|
||||||
throw ioe;
|
throw ioe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.util;
|
||||||
|
|
||||||
|
public class EscapeUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes the specified html by replacing &, <, >, ", ', /
|
||||||
|
* with their corresponding html entity. If html is null, null is returned.
|
||||||
|
*
|
||||||
|
* @param html
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String escapeHtml(String html) {
|
||||||
|
if (html == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
html = html.replace("&", "&");
|
||||||
|
html = html.replace("<", "<");
|
||||||
|
html = html.replace(">", ">");
|
||||||
|
html = html.replace("\"", """);
|
||||||
|
html = html.replace("'", "'");
|
||||||
|
html = html.replace("/", "/");
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,5 +36,6 @@
|
||||||
<module>nifi-processor-utilities</module>
|
<module>nifi-processor-utilities</module>
|
||||||
<module>nifi-write-ahead-log</module>
|
<module>nifi-write-ahead-log</module>
|
||||||
<module>nifi-site-to-site-client</module>
|
<module>nifi-site-to-site-client</module>
|
||||||
|
<module>nifi-hl7-query-language</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -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-aws-bundle</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nifi-aws-nar</artifactId>
|
||||||
|
<packaging>nar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-aws-processors</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?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-aws-bundle</artifactId>
|
||||||
|
<version>0.1.0-incubating-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nifi-aws-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>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk</artifactId>
|
||||||
|
</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>
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.aws;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.lifecycle.OnScheduled;
|
||||||
|
import org.apache.nifi.components.AllowableValue;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.components.ValidationContext;
|
||||||
|
import org.apache.nifi.components.ValidationResult;
|
||||||
|
import org.apache.nifi.processor.AbstractProcessor;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.Relationship;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.AmazonWebServiceClient;
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
|
import com.amazonaws.auth.AnonymousAWSCredentials;
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
|
import com.amazonaws.auth.PropertiesCredentials;
|
||||||
|
import com.amazonaws.regions.Region;
|
||||||
|
import com.amazonaws.regions.Regions;
|
||||||
|
|
||||||
|
public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceClient> extends AbstractProcessor {
|
||||||
|
|
||||||
|
public static final Relationship REL_SUCCESS = new Relationship.Builder().name("success")
|
||||||
|
.description("FlowFiles are routed to success after being successfully copied to Amazon S3").build();
|
||||||
|
public static final Relationship REL_FAILURE = new Relationship.Builder().name("failure")
|
||||||
|
.description("FlowFiles are routed to failure if unable to be copied to Amazon S3").build();
|
||||||
|
|
||||||
|
public static final Set<Relationship> relationships = Collections.unmodifiableSet(
|
||||||
|
new HashSet<>(Arrays.asList(REL_SUCCESS, REL_FAILURE)));
|
||||||
|
|
||||||
|
public static final PropertyDescriptor CREDENTAILS_FILE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Credentials File")
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor ACCESS_KEY = new PropertyDescriptor.Builder()
|
||||||
|
.name("Access Key")
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.sensitive(true)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor SECRET_KEY = new PropertyDescriptor.Builder()
|
||||||
|
.name("Secret Key")
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.sensitive(true)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor REGION = new PropertyDescriptor.Builder()
|
||||||
|
.name("Region")
|
||||||
|
.required(true)
|
||||||
|
.allowableValues(getAvailableRegions())
|
||||||
|
.defaultValue(createAllowableValue(Regions.DEFAULT_REGION).getValue())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor TIMEOUT = new PropertyDescriptor.Builder()
|
||||||
|
.name("Communications Timeout")
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
|
||||||
|
.defaultValue("30 secs")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
private volatile ClientType client;
|
||||||
|
|
||||||
|
|
||||||
|
private static AllowableValue createAllowableValue(final Regions regions) {
|
||||||
|
return new AllowableValue(regions.getName(), regions.getName(), regions.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AllowableValue[] getAvailableRegions() {
|
||||||
|
final List<AllowableValue> values = new ArrayList<>();
|
||||||
|
for ( final Regions regions : Regions.values() ) {
|
||||||
|
values.add(createAllowableValue(regions));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (AllowableValue[]) values.toArray(new AllowableValue[values.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Relationship> getRelationships() {
|
||||||
|
return relationships;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) {
|
||||||
|
final List<ValidationResult> problems = new ArrayList<>(super.customValidate(validationContext));
|
||||||
|
|
||||||
|
final boolean accessKeySet = validationContext.getProperty(ACCESS_KEY).isSet();
|
||||||
|
final boolean secretKeySet = validationContext.getProperty(SECRET_KEY).isSet();
|
||||||
|
if ( (accessKeySet && !secretKeySet) || (secretKeySet && !accessKeySet) ) {
|
||||||
|
problems.add(new ValidationResult.Builder().input("Access Key").valid(false).explanation("If setting Secret Key or Access Key, must set both").build());
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean credentialsFileSet = validationContext.getProperty(CREDENTAILS_FILE).isSet();
|
||||||
|
if ( (secretKeySet || accessKeySet) && credentialsFileSet ) {
|
||||||
|
problems.add(new ValidationResult.Builder().input("Access Key").valid(false).explanation("Cannot set both Credentials File and Secret Key/Access Key").build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return problems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ClientConfiguration createConfiguration(final ProcessContext context) {
|
||||||
|
final ClientConfiguration config = new ClientConfiguration();
|
||||||
|
config.setMaxConnections(context.getMaxConcurrentTasks());
|
||||||
|
config.setMaxErrorRetry(0);
|
||||||
|
config.setUserAgent("NiFi");
|
||||||
|
|
||||||
|
final int commsTimeout = context.getProperty(TIMEOUT).asTimePeriod(TimeUnit.MILLISECONDS).intValue();
|
||||||
|
config.setConnectionTimeout(commsTimeout);
|
||||||
|
config.setSocketTimeout(commsTimeout);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OnScheduled
|
||||||
|
public void onScheduled(final ProcessContext context) {
|
||||||
|
final ClientType awsClient = createClient(context, getCredentials(context), createConfiguration(context));
|
||||||
|
this.client = awsClient;
|
||||||
|
|
||||||
|
// if the processor supports REGION, get the configured region.
|
||||||
|
if ( getSupportedPropertyDescriptors().contains(REGION) ) {
|
||||||
|
final String region = context.getProperty(REGION).getValue();
|
||||||
|
if ( region != null ) {
|
||||||
|
client.setRegion(Region.getRegion(Regions.fromName(region)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ClientType createClient(final ProcessContext context, final AWSCredentials credentials, final ClientConfiguration config);
|
||||||
|
|
||||||
|
protected ClientType getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AWSCredentials getCredentials(final ProcessContext context) {
|
||||||
|
final String accessKey = context.getProperty(ACCESS_KEY).getValue();
|
||||||
|
final String secretKey = context.getProperty(SECRET_KEY).getValue();
|
||||||
|
|
||||||
|
final String credentialsFile = context.getProperty(CREDENTAILS_FILE).getValue();
|
||||||
|
|
||||||
|
if ( credentialsFile != null ) {
|
||||||
|
try {
|
||||||
|
return new PropertiesCredentials(new File(credentialsFile));
|
||||||
|
} catch (final IOException ioe) {
|
||||||
|
throw new ProcessException("Could not read Credentials File", ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( accessKey != null && secretKey != null ) {
|
||||||
|
return new BasicAWSCredentials(accessKey, secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AnonymousAWSCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected boolean isEmpty(final String value) {
|
||||||
|
return value == null || value.trim().equals("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.s3;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.processors.aws.AbstractAWSProcessor;
|
||||||
|
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import com.amazonaws.services.s3.model.AccessControlList;
|
||||||
|
import com.amazonaws.services.s3.model.CanonicalGrantee;
|
||||||
|
import com.amazonaws.services.s3.model.EmailAddressGrantee;
|
||||||
|
import com.amazonaws.services.s3.model.Grantee;
|
||||||
|
import com.amazonaws.services.s3.model.Owner;
|
||||||
|
import com.amazonaws.services.s3.model.Permission;
|
||||||
|
|
||||||
|
public abstract class AbstractS3Processor extends AbstractAWSProcessor<AmazonS3Client> {
|
||||||
|
|
||||||
|
public static final PropertyDescriptor FULL_CONTROL_USER_LIST = new PropertyDescriptor.Builder()
|
||||||
|
.name("FullControl User List")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("A comma-separated list of Amazon User ID's or E-mail addresses that specifies who should have Full Control for an object")
|
||||||
|
.defaultValue("${s3.permissions.full.users}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor READ_USER_LIST = new PropertyDescriptor.Builder()
|
||||||
|
.name("Read Permission User List")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("A comma-separated list of Amazon User ID's or E-mail addresses that specifies who should have Read Access for an object")
|
||||||
|
.defaultValue("${s3.permissions.read.users}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor WRITE_USER_LIST = new PropertyDescriptor.Builder()
|
||||||
|
.name("Write Permission User List")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("A comma-separated list of Amazon User ID's or E-mail addresses that specifies who should have Write Access for an object")
|
||||||
|
.defaultValue("${s3.permissions.write.users}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor READ_ACL_LIST = new PropertyDescriptor.Builder()
|
||||||
|
.name("Read ACL User List")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("A comma-separated list of Amazon User ID's or E-mail addresses that specifies who should have permissions to read the Access Control List for an object")
|
||||||
|
.defaultValue("${s3.permissions.readacl.users}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor WRITE_ACL_LIST = new PropertyDescriptor.Builder()
|
||||||
|
.name("Write ACL User List")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("A comma-separated list of Amazon User ID's or E-mail addresses that specifies who should have permissions to change the Access Control List for an object")
|
||||||
|
.defaultValue("${s3.permissions.writeacl.users}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor OWNER = new PropertyDescriptor.Builder()
|
||||||
|
.name("Owner")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.description("The Amazon ID to use for the object's owner")
|
||||||
|
.defaultValue("${s3.owner}")
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor BUCKET = new PropertyDescriptor.Builder()
|
||||||
|
.name("Bucket")
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor KEY = new PropertyDescriptor.Builder()
|
||||||
|
.name("Object Key")
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.defaultValue("${filename}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AmazonS3Client createClient(final ProcessContext context, final AWSCredentials credentials, final ClientConfiguration config) {
|
||||||
|
return new AmazonS3Client(credentials, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Grantee createGrantee(final String value) {
|
||||||
|
if ( isEmpty(value) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( value.contains("@") ) {
|
||||||
|
return new EmailAddressGrantee(value);
|
||||||
|
} else {
|
||||||
|
return new CanonicalGrantee(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final List<Grantee> createGrantees(final String value) {
|
||||||
|
if ( isEmpty(value) ) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Grantee> grantees = new ArrayList<>();
|
||||||
|
final String[] vals = value.split(",");
|
||||||
|
for ( final String val : vals ) {
|
||||||
|
final String identifier = val.trim();
|
||||||
|
final Grantee grantee = createGrantee(identifier);
|
||||||
|
if ( grantee != null ) {
|
||||||
|
grantees.add(grantee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grantees;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final AccessControlList createACL(final ProcessContext context, final FlowFile flowFile) {
|
||||||
|
final AccessControlList acl = new AccessControlList();
|
||||||
|
|
||||||
|
final String ownerId = context.getProperty(OWNER).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
if ( !isEmpty(ownerId) ) {
|
||||||
|
final Owner owner = new Owner();
|
||||||
|
owner.setId(ownerId);
|
||||||
|
acl.setOwner(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Grantee grantee : createGrantees(context.getProperty(FULL_CONTROL_USER_LIST).evaluateAttributeExpressions(flowFile).getValue())) {
|
||||||
|
acl.grantPermission(grantee, Permission.FullControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Grantee grantee : createGrantees(context.getProperty(READ_USER_LIST).evaluateAttributeExpressions(flowFile).getValue())) {
|
||||||
|
acl.grantPermission(grantee, Permission.Read);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Grantee grantee : createGrantees(context.getProperty(WRITE_USER_LIST).evaluateAttributeExpressions(flowFile).getValue())) {
|
||||||
|
acl.grantPermission(grantee, Permission.Write);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Grantee grantee : createGrantees(context.getProperty(READ_ACL_LIST).evaluateAttributeExpressions(flowFile).getValue())) {
|
||||||
|
acl.grantPermission(grantee, Permission.ReadAcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Grantee grantee : createGrantees(context.getProperty(WRITE_ACL_LIST).evaluateAttributeExpressions(flowFile).getValue())) {
|
||||||
|
acl.grantPermission(grantee, Permission.WriteAcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.s3;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
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.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.AmazonClientException;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3;
|
||||||
|
import com.amazonaws.services.s3.model.GetObjectRequest;
|
||||||
|
import com.amazonaws.services.s3.model.ObjectMetadata;
|
||||||
|
import com.amazonaws.services.s3.model.S3Object;
|
||||||
|
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@SeeAlso({PutS3Object.class})
|
||||||
|
@Tags({"Amazon", "S3", "AWS", "Get", "Fetch"})
|
||||||
|
@CapabilityDescription("Retrieves the contents of an S3 Object and writes it to the content of a FlowFile")
|
||||||
|
@WritesAttributes({
|
||||||
|
@WritesAttribute(attribute="s3.bucket", description="The name of the S3 bucket"),
|
||||||
|
@WritesAttribute(attribute="path", description="The path of the file"),
|
||||||
|
@WritesAttribute(attribute="absolute.path", description="The path of the file"),
|
||||||
|
@WritesAttribute(attribute="filename", description="The name of the file"),
|
||||||
|
@WritesAttribute(attribute="hash.value", description="The MD5 sum of the file"),
|
||||||
|
@WritesAttribute(attribute="hash.algorithm", description="MD5"),
|
||||||
|
@WritesAttribute(attribute="mime.type", description="If S3 provides the content type/MIME type, this attribute will hold that file"),
|
||||||
|
@WritesAttribute(attribute="s3.etag", description="The ETag that can be used to see if the file has changed"),
|
||||||
|
@WritesAttribute(attribute="s3.expirationTime", description="If the file has an expiration date, this attribute will be set, containing the milliseconds since epoch in UTC time"),
|
||||||
|
@WritesAttribute(attribute="s3.expirationTimeRuleId", description="The ID of the rule that dictates this object's expiration time"),
|
||||||
|
@WritesAttribute(attribute="s3.version", description="The version of the S3 object"),
|
||||||
|
})
|
||||||
|
public class FetchS3Object extends AbstractS3Processor {
|
||||||
|
|
||||||
|
public static final PropertyDescriptor VERSION_ID = new PropertyDescriptor.Builder()
|
||||||
|
.name("Version")
|
||||||
|
.description("The Version of the Object to download")
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(BUCKET, KEY, REGION, ACCESS_KEY, SECRET_KEY, CREDENTAILS_FILE, TIMEOUT, VERSION_ID) );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
FlowFile flowFile = session.get();
|
||||||
|
if ( flowFile == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long startNanos = System.nanoTime();
|
||||||
|
final String bucket = context.getProperty(BUCKET).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
final String key = context.getProperty(KEY).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
final String versionId = context.getProperty(VERSION_ID).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
|
||||||
|
final AmazonS3 client = getClient();
|
||||||
|
final GetObjectRequest request;
|
||||||
|
if ( versionId == null ) {
|
||||||
|
request = new GetObjectRequest(bucket, key);
|
||||||
|
} else {
|
||||||
|
request = new GetObjectRequest(bucket, key, versionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
try (final S3Object s3Object = client.getObject(request)) {
|
||||||
|
flowFile = session.importFrom(s3Object.getObjectContent(), flowFile);
|
||||||
|
attributes.put("s3.bucket", s3Object.getBucketName());
|
||||||
|
|
||||||
|
final ObjectMetadata metadata = s3Object.getObjectMetadata();
|
||||||
|
if ( metadata.getContentDisposition() != null ) {
|
||||||
|
final String fullyQualified = metadata.getContentDisposition();
|
||||||
|
final int lastSlash = fullyQualified.lastIndexOf("/");
|
||||||
|
if ( lastSlash > -1 && lastSlash < fullyQualified.length() - 1 ) {
|
||||||
|
attributes.put(CoreAttributes.PATH.key(), fullyQualified.substring(0, lastSlash));
|
||||||
|
attributes.put(CoreAttributes.ABSOLUTE_PATH.key(), fullyQualified);
|
||||||
|
attributes.put(CoreAttributes.FILENAME.key(), fullyQualified.substring(lastSlash + 1));
|
||||||
|
} else {
|
||||||
|
attributes.put(CoreAttributes.FILENAME.key(), metadata.getContentDisposition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (metadata.getContentMD5() != null ) {
|
||||||
|
attributes.put("hash.value", metadata.getContentMD5());
|
||||||
|
attributes.put("hash.algorithm", "MD5");
|
||||||
|
}
|
||||||
|
if ( metadata.getContentType() != null ) {
|
||||||
|
attributes.put(CoreAttributes.MIME_TYPE.key(), metadata.getContentType());
|
||||||
|
}
|
||||||
|
if ( metadata.getETag() != null ) {
|
||||||
|
attributes.put("s3.etag", metadata.getETag());
|
||||||
|
}
|
||||||
|
if ( metadata.getExpirationTime() != null ) {
|
||||||
|
attributes.put("s3.expirationTime", String.valueOf(metadata.getExpirationTime().getTime()));
|
||||||
|
}
|
||||||
|
if ( metadata.getExpirationTimeRuleId() != null ) {
|
||||||
|
attributes.put("s3.expirationTimeRuleId", metadata.getExpirationTimeRuleId());
|
||||||
|
}
|
||||||
|
if ( metadata.getUserMetadata() != null ) {
|
||||||
|
attributes.putAll(metadata.getUserMetadata());
|
||||||
|
}
|
||||||
|
if ( metadata.getVersionId() != null ) {
|
||||||
|
attributes.put("s3.version", metadata.getVersionId());
|
||||||
|
}
|
||||||
|
} catch (final IOException | AmazonClientException ioe) {
|
||||||
|
getLogger().error("Failed to retrieve S3 Object for {}; routing to failure", new Object[] {flowFile, ioe});
|
||||||
|
session.transfer(flowFile, REL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !attributes.isEmpty() ) {
|
||||||
|
flowFile = session.putAllAttributes(flowFile, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.transfer(flowFile, REL_SUCCESS);
|
||||||
|
final long transferMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
|
||||||
|
getLogger().info("Successfully retrieved S3 Object for {} in {} millis; routing to success", new Object[] {flowFile, transferMillis});
|
||||||
|
session.getProvenanceReporter().receive(flowFile, "http://" + bucket + ".amazonaws.com/" + key, transferMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.s3;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.behavior.DynamicProperty;
|
||||||
|
import org.apache.nifi.annotation.behavior.ReadsAttribute;
|
||||||
|
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.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
import org.apache.nifi.processor.io.InputStreamCallback;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.AmazonClientException;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3;
|
||||||
|
import com.amazonaws.services.s3.model.AccessControlList;
|
||||||
|
import com.amazonaws.services.s3.model.ObjectMetadata;
|
||||||
|
import com.amazonaws.services.s3.model.PutObjectRequest;
|
||||||
|
import com.amazonaws.services.s3.model.PutObjectResult;
|
||||||
|
import com.amazonaws.services.s3.model.StorageClass;
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@SeeAlso({FetchS3Object.class})
|
||||||
|
@Tags({"Amazon", "S3", "AWS", "Archive", "Put"})
|
||||||
|
@CapabilityDescription("Puts FlowFiles to an Amazon S3 Bucket")
|
||||||
|
@DynamicProperty(name="The name of a User-Defined Metadata field to add to the S3 Object",
|
||||||
|
value="The value of a User-Defined Metadata field to add to the S3 Object",
|
||||||
|
description="Allows user-defined metadata to be added to the S3 object as key/value pairs",
|
||||||
|
supportsExpressionLanguage=true)
|
||||||
|
@ReadsAttribute(attribute="filename", description="Uses the FlowFile's filename as the filename for the S3 object")
|
||||||
|
@WritesAttributes({
|
||||||
|
@WritesAttribute(attribute="s3.version", description="The version of the S3 Object that was put to S3"),
|
||||||
|
@WritesAttribute(attribute="s3.etag", description="The ETag of the S3 Object"),
|
||||||
|
@WritesAttribute(attribute="s3.expiration", description="A human-readable form of the expiration date of the S3 object, if one is set")
|
||||||
|
})
|
||||||
|
public class PutS3Object extends AbstractS3Processor {
|
||||||
|
public static final PropertyDescriptor EXPIRATION_RULE_ID = new PropertyDescriptor.Builder()
|
||||||
|
.name("Expiration Time Rule")
|
||||||
|
.required(false)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor STORAGE_CLASS = new PropertyDescriptor.Builder()
|
||||||
|
.name("Storage Class")
|
||||||
|
.required(true)
|
||||||
|
.allowableValues(StorageClass.Standard.name(), StorageClass.ReducedRedundancy.name())
|
||||||
|
.defaultValue(StorageClass.Standard.name())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(KEY, BUCKET, ACCESS_KEY, SECRET_KEY, CREDENTAILS_FILE, STORAGE_CLASS, REGION, TIMEOUT, EXPIRATION_RULE_ID,
|
||||||
|
FULL_CONTROL_USER_LIST, READ_USER_LIST, WRITE_USER_LIST, READ_ACL_LIST, WRITE_ACL_LIST, OWNER) );
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
||||||
|
return new PropertyDescriptor.Builder()
|
||||||
|
.name(propertyDescriptorName)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.dynamic(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
FlowFile flowFile = session.get();
|
||||||
|
if ( flowFile == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long startNanos = System.nanoTime();
|
||||||
|
|
||||||
|
final String bucket = context.getProperty(BUCKET).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
final String key = context.getProperty(KEY).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
|
||||||
|
final AmazonS3 s3 = getClient();
|
||||||
|
final FlowFile ff = flowFile;
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
try {
|
||||||
|
session.read(flowFile, new InputStreamCallback() {
|
||||||
|
@Override
|
||||||
|
public void process(final InputStream rawIn) throws IOException {
|
||||||
|
try (final InputStream in = new BufferedInputStream(rawIn)) {
|
||||||
|
final ObjectMetadata objectMetadata = new ObjectMetadata();
|
||||||
|
objectMetadata.setContentDisposition(ff.getAttribute(CoreAttributes.FILENAME.key()));
|
||||||
|
objectMetadata.setContentLength(ff.getSize());
|
||||||
|
|
||||||
|
final String expirationRule = context.getProperty(EXPIRATION_RULE_ID).evaluateAttributeExpressions(ff).getValue();
|
||||||
|
if ( expirationRule != null ) {
|
||||||
|
objectMetadata.setExpirationTimeRuleId(expirationRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> userMetadata = new HashMap<>();
|
||||||
|
for ( final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet() ) {
|
||||||
|
if ( entry.getKey().isDynamic() ) {
|
||||||
|
final String value = context.getProperty(entry.getKey()).evaluateAttributeExpressions(ff).getValue();
|
||||||
|
userMetadata.put(entry.getKey().getName(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !userMetadata.isEmpty() ) {
|
||||||
|
objectMetadata.setUserMetadata(userMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
final PutObjectRequest request = new PutObjectRequest(bucket, key, in, objectMetadata);
|
||||||
|
request.setStorageClass(StorageClass.valueOf(context.getProperty(STORAGE_CLASS).getValue()));
|
||||||
|
final AccessControlList acl = createACL(context, ff);
|
||||||
|
if ( acl != null ) {
|
||||||
|
request.setAccessControlList(acl);
|
||||||
|
}
|
||||||
|
|
||||||
|
final PutObjectResult result = s3.putObject(request);
|
||||||
|
if ( result.getVersionId() != null ) {
|
||||||
|
attributes.put("s3.version", result.getVersionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes.put("s3.etag", result.getETag());
|
||||||
|
|
||||||
|
final Date expiration = result.getExpirationTime();
|
||||||
|
if ( expiration != null ) {
|
||||||
|
attributes.put("s3.expiration", expiration.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( !attributes.isEmpty() ) {
|
||||||
|
flowFile = session.putAllAttributes(flowFile, attributes);
|
||||||
|
}
|
||||||
|
session.transfer(flowFile, REL_SUCCESS);
|
||||||
|
|
||||||
|
final String url = "http://" + bucket + ".s3.amazonaws.com/" + key;
|
||||||
|
final long millis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
|
||||||
|
session.getProvenanceReporter().send(flowFile, url, millis);
|
||||||
|
|
||||||
|
getLogger().info("Successfully put {} to Amazon S3 in {} milliseconds", new Object[] {ff, millis});
|
||||||
|
} catch (final ProcessException | AmazonClientException pe) {
|
||||||
|
getLogger().error("Failed to put {} to Amazon S3 due to {}", new Object[] {flowFile, pe});
|
||||||
|
session.transfer(flowFile, REL_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.sns;
|
||||||
|
|
||||||
|
import org.apache.nifi.components.AllowableValue;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.processors.aws.AbstractAWSProcessor;
|
||||||
|
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
|
import com.amazonaws.services.sns.AmazonSNSClient;
|
||||||
|
|
||||||
|
public abstract class AbstractSNSProcessor extends AbstractAWSProcessor<AmazonSNSClient> {
|
||||||
|
|
||||||
|
protected static final AllowableValue ARN_TYPE_TOPIC =
|
||||||
|
new AllowableValue("Topic ARN", "Topic ARN", "The ARN is the name of a topic");
|
||||||
|
protected static final AllowableValue ARN_TYPE_TARGET =
|
||||||
|
new AllowableValue("Target ARN", "Target ARN", "The ARN is the name of a particular Target, used to notify a specific subscriber");
|
||||||
|
|
||||||
|
public static final PropertyDescriptor ARN = new PropertyDescriptor.Builder()
|
||||||
|
.name("Amazon Resource Name (ARN)")
|
||||||
|
.description("The name of the resource to which notifications should be published")
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor ARN_TYPE = new PropertyDescriptor.Builder()
|
||||||
|
.name("ARN Type")
|
||||||
|
.description("The type of Amazon Resource Name that is being used.")
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.required(true)
|
||||||
|
.allowableValues(ARN_TYPE_TOPIC, ARN_TYPE_TARGET)
|
||||||
|
.defaultValue(ARN_TYPE_TOPIC.getValue())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AmazonSNSClient createClient(final ProcessContext context, final AWSCredentials credentials, final ClientConfiguration config) {
|
||||||
|
return new AmazonSNSClient(credentials, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.sns;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.behavior.SupportsBatching;
|
||||||
|
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||||
|
import org.apache.nifi.annotation.documentation.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.processors.aws.sqs.GetSQS;
|
||||||
|
import org.apache.nifi.processors.aws.sqs.PutSQS;
|
||||||
|
|
||||||
|
import com.amazonaws.services.sns.AmazonSNSClient;
|
||||||
|
import com.amazonaws.services.sns.model.MessageAttributeValue;
|
||||||
|
import com.amazonaws.services.sns.model.PublishRequest;
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@SeeAlso({GetSQS.class, PutSQS.class})
|
||||||
|
@Tags({"amazon", "aws", "sns", "topic", "put", "publish", "pubsub"})
|
||||||
|
@CapabilityDescription("Sends the content of a FlowFile as a notification to the Amazon Simple Notification Service")
|
||||||
|
public class PutSNS extends AbstractSNSProcessor {
|
||||||
|
|
||||||
|
public static final PropertyDescriptor CHARACTER_ENCODING = new PropertyDescriptor.Builder()
|
||||||
|
.name("Character Set")
|
||||||
|
.description("The character set in which the FlowFile's content is encoded")
|
||||||
|
.defaultValue("UTF-8")
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.addValidator(StandardValidators.CHARACTER_SET_VALIDATOR)
|
||||||
|
.required(true)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor USE_JSON_STRUCTURE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Use JSON Structure")
|
||||||
|
.description("If true, the contents of the FlowFile must be JSON with a top-level element named 'default'. Additional elements can be used to send different messages to different protocols. See the Amazon SNS Documentation for more information.")
|
||||||
|
.defaultValue("false")
|
||||||
|
.allowableValues("true", "false")
|
||||||
|
.required(true)
|
||||||
|
.build();
|
||||||
|
public static final PropertyDescriptor SUBJECT = new PropertyDescriptor.Builder()
|
||||||
|
.name("E-mail Subject")
|
||||||
|
.description("The optional subject to use for any subscribers that are subscribed via E-mail")
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(ARN, ARN_TYPE, SUBJECT, REGION, ACCESS_KEY, SECRET_KEY, CREDENTAILS_FILE, TIMEOUT,
|
||||||
|
USE_JSON_STRUCTURE, CHARACTER_ENCODING) );
|
||||||
|
|
||||||
|
public static final int MAX_SIZE = 256 * 1024;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
||||||
|
return new PropertyDescriptor.Builder()
|
||||||
|
.name(propertyDescriptorName)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(false)
|
||||||
|
.dynamic(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
FlowFile flowFile = session.get();
|
||||||
|
if ( flowFile == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flowFile.getSize() > MAX_SIZE ) {
|
||||||
|
getLogger().error("Cannot publish {} to SNS because its size exceeds Amazon SNS's limit of 256KB; routing to failure", new Object[] {flowFile});
|
||||||
|
session.transfer(flowFile, REL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Charset charset = Charset.forName(context.getProperty(CHARACTER_ENCODING).evaluateAttributeExpressions(flowFile).getValue());
|
||||||
|
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
session.exportTo(flowFile, baos);
|
||||||
|
final String message = new String(baos.toByteArray(), charset);
|
||||||
|
|
||||||
|
final AmazonSNSClient client = getClient();
|
||||||
|
final PublishRequest request = new PublishRequest();
|
||||||
|
request.setMessage(message);
|
||||||
|
|
||||||
|
if ( context.getProperty(USE_JSON_STRUCTURE).asBoolean() ) {
|
||||||
|
request.setMessageStructure("json");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String arn = context.getProperty(ARN).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
final String arnType = context.getProperty(ARN_TYPE).getValue();
|
||||||
|
if ( arnType.equalsIgnoreCase(ARN_TYPE_TOPIC.getValue()) ) {
|
||||||
|
request.setTopicArn(arn);
|
||||||
|
} else {
|
||||||
|
request.setTargetArn(arn);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String subject = context.getProperty(SUBJECT).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
if ( subject != null ) {
|
||||||
|
request.setSubject(subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Map.Entry<PropertyDescriptor, String> entry : context.getProperties().entrySet() ) {
|
||||||
|
if ( entry.getKey().isDynamic() && !isEmpty(entry.getValue()) ) {
|
||||||
|
final MessageAttributeValue value = new MessageAttributeValue();
|
||||||
|
value.setStringValue(context.getProperty(entry.getKey()).evaluateAttributeExpressions(flowFile).getValue());
|
||||||
|
value.setDataType("String");
|
||||||
|
request.addMessageAttributesEntry(entry.getKey().getName(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.publish(request);
|
||||||
|
session.transfer(flowFile, REL_SUCCESS);
|
||||||
|
session.getProvenanceReporter().send(flowFile, arn);
|
||||||
|
getLogger().info("Successfully published notification for {}", new Object[] {flowFile});
|
||||||
|
} catch (final Exception e) {
|
||||||
|
getLogger().error("Failed to publish Amazon SNS message for {} due to {}", new Object[] {flowFile, e});
|
||||||
|
session.transfer(flowFile, REL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.processors.aws.sqs;
|
||||||
|
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.processors.aws.AbstractAWSProcessor;
|
||||||
|
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSClient;
|
||||||
|
|
||||||
|
public abstract class AbstractSQSProcessor extends AbstractAWSProcessor<AmazonSQSClient> {
|
||||||
|
|
||||||
|
public static final PropertyDescriptor BATCH_SIZE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Batch Size")
|
||||||
|
.description("The maximum number of messages to send in a single network request")
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
|
||||||
|
.defaultValue("25")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor QUEUE_URL = new PropertyDescriptor.Builder()
|
||||||
|
.name("Queue URL")
|
||||||
|
.description("The URL of the queue to act upon")
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AmazonSQSClient createClient(final ProcessContext context, final AWSCredentials credentials, final ClientConfiguration config) {
|
||||||
|
return new AmazonSQSClient(credentials, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.sqs;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.behavior.SupportsBatching;
|
||||||
|
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||||
|
import org.apache.nifi.annotation.documentation.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSClient;
|
||||||
|
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequest;
|
||||||
|
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequestEntry;
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@SeeAlso({GetSQS.class, PutSQS.class})
|
||||||
|
@Tags({"Amazon", "AWS", "SQS", "Queue", "Delete"})
|
||||||
|
@CapabilityDescription("Deletes a message from an Amazon Simple Queuing Service Queue")
|
||||||
|
public class DeleteSQS extends AbstractSQSProcessor {
|
||||||
|
public static final PropertyDescriptor RECEIPT_HANDLE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Receipt Handle")
|
||||||
|
.description("The identifier that specifies the receipt of the message")
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.defaultValue("${sqs.receipt.handle}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(ACCESS_KEY, SECRET_KEY, REGION, QUEUE_URL, TIMEOUT) );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
List<FlowFile> flowFiles = session.get(1);
|
||||||
|
if ( flowFiles.isEmpty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FlowFile firstFlowFile = flowFiles.get(0);
|
||||||
|
final String queueUrl = context.getProperty(QUEUE_URL).evaluateAttributeExpressions(firstFlowFile).getValue();
|
||||||
|
|
||||||
|
final AmazonSQSClient client = getClient();
|
||||||
|
final DeleteMessageBatchRequest request = new DeleteMessageBatchRequest();
|
||||||
|
request.setQueueUrl(queueUrl);
|
||||||
|
|
||||||
|
final List<DeleteMessageBatchRequestEntry> entries = new ArrayList<>(flowFiles.size());
|
||||||
|
|
||||||
|
for ( final FlowFile flowFile : flowFiles ) {
|
||||||
|
final DeleteMessageBatchRequestEntry entry = new DeleteMessageBatchRequestEntry();
|
||||||
|
entry.setReceiptHandle(context.getProperty(RECEIPT_HANDLE).evaluateAttributeExpressions(flowFile).getValue());
|
||||||
|
entries.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.setEntries(entries);
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.deleteMessageBatch(request);
|
||||||
|
getLogger().info("Successfully deleted {} objects from SQS", new Object[] {flowFiles.size()});
|
||||||
|
session.transfer(flowFiles, REL_SUCCESS);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
getLogger().error("Failed to delete {} objects from SQS due to {}", new Object[] {flowFiles.size(), e});
|
||||||
|
session.transfer(flowFiles, REL_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.sqs;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
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.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.Relationship;
|
||||||
|
import org.apache.nifi.processor.io.OutputStreamCallback;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSClient;
|
||||||
|
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequest;
|
||||||
|
import com.amazonaws.services.sqs.model.DeleteMessageBatchRequestEntry;
|
||||||
|
import com.amazonaws.services.sqs.model.Message;
|
||||||
|
import com.amazonaws.services.sqs.model.MessageAttributeValue;
|
||||||
|
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
|
||||||
|
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@Tags({ "Amazon", "AWS", "SQS", "Queue", "Get", "Fetch", "Poll"})
|
||||||
|
@SeeAlso({PutSQS.class, DeleteSQS.class})
|
||||||
|
@CapabilityDescription("Fetches messages from an Amazon Simple Queuing Service Queue")
|
||||||
|
@WritesAttributes({
|
||||||
|
@WritesAttribute(attribute="hash.value", description="The MD5 sum of the message"),
|
||||||
|
@WritesAttribute(attribute="hash.algorithm", description="MD5"),
|
||||||
|
@WritesAttribute(attribute="sqs.message.id", description="The unique identifier of the SQS message"),
|
||||||
|
@WritesAttribute(attribute="sqs.receipt.handle", description="The SQS Receipt Handle that is to be used to delete the message from the queue")
|
||||||
|
})
|
||||||
|
public class GetSQS extends AbstractSQSProcessor {
|
||||||
|
public static final PropertyDescriptor CHARSET = new PropertyDescriptor.Builder()
|
||||||
|
.name("Character Set")
|
||||||
|
.description("The Character Set that should be used to encode the textual content of the SQS message")
|
||||||
|
.required(true)
|
||||||
|
.defaultValue("UTF-8")
|
||||||
|
.allowableValues(Charset.availableCharsets().keySet().toArray(new String[0]))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor AUTO_DELETE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Auto Delete Messages")
|
||||||
|
.description("Specifies whether the messages should be automatically deleted by the processors once they have been received.")
|
||||||
|
.required(true)
|
||||||
|
.allowableValues("true", "false")
|
||||||
|
.defaultValue("true")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor VISIBILITY_TIMEOUT = new PropertyDescriptor.Builder()
|
||||||
|
.name("Visibility Timeout")
|
||||||
|
.description("The amount of time after a message is received but not deleted that the message is hidden from other consumers")
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.required(true)
|
||||||
|
.defaultValue("15 mins")
|
||||||
|
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final PropertyDescriptor BATCH_SIZE = new PropertyDescriptor.Builder()
|
||||||
|
.name("Batch Size")
|
||||||
|
.description("The maximum number of messages to send in a single network request")
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.createLongValidator(1L, 10L, true))
|
||||||
|
.defaultValue("10")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
public static final PropertyDescriptor STATIC_QUEUE_URL = new PropertyDescriptor.Builder()
|
||||||
|
.fromPropertyDescriptor(QUEUE_URL)
|
||||||
|
.expressionLanguageSupported(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(STATIC_QUEUE_URL, AUTO_DELETE, ACCESS_KEY, SECRET_KEY, CREDENTAILS_FILE, REGION, BATCH_SIZE, TIMEOUT, CHARSET, VISIBILITY_TIMEOUT) );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Relationship> getRelationships() {
|
||||||
|
return Collections.singleton(REL_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
final String queueUrl = context.getProperty(STATIC_QUEUE_URL).getValue();
|
||||||
|
|
||||||
|
final AmazonSQSClient client = getClient();
|
||||||
|
|
||||||
|
final ReceiveMessageRequest request = new ReceiveMessageRequest();
|
||||||
|
request.setAttributeNames(Collections.singleton("All"));
|
||||||
|
request.setMaxNumberOfMessages(context.getProperty(BATCH_SIZE).asInteger());
|
||||||
|
request.setVisibilityTimeout(context.getProperty(VISIBILITY_TIMEOUT).asTimePeriod(TimeUnit.SECONDS).intValue());
|
||||||
|
request.setQueueUrl(queueUrl);
|
||||||
|
|
||||||
|
final Charset charset = Charset.forName(context.getProperty(CHARSET).getValue());
|
||||||
|
|
||||||
|
final ReceiveMessageResult result;
|
||||||
|
try {
|
||||||
|
result = client.receiveMessage(request);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
getLogger().error("Failed to receive messages from Amazon SQS due to {}", new Object[] {e});
|
||||||
|
context.yield();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Message> messages = result.getMessages();
|
||||||
|
if ( messages.isEmpty() ) {
|
||||||
|
context.yield();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean autoDelete = context.getProperty(AUTO_DELETE).asBoolean();
|
||||||
|
|
||||||
|
for ( final Message message : messages ) {
|
||||||
|
FlowFile flowFile = session.create();
|
||||||
|
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
for ( final Map.Entry<String, String> entry : message.getAttributes().entrySet() ) {
|
||||||
|
attributes.put("sqs." + entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( final Map.Entry<String, MessageAttributeValue> entry : message.getMessageAttributes().entrySet() ) {
|
||||||
|
attributes.put("sqs." + entry.getKey(), entry.getValue().getStringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes.put("hash.value", message.getMD5OfBody());
|
||||||
|
attributes.put("hash.algorithm", "md5");
|
||||||
|
attributes.put("sqs.message.id", message.getMessageId());
|
||||||
|
attributes.put("sqs.receipt.handle", message.getReceiptHandle());
|
||||||
|
|
||||||
|
flowFile = session.putAllAttributes(flowFile, attributes);
|
||||||
|
flowFile = session.write(flowFile, new OutputStreamCallback() {
|
||||||
|
@Override
|
||||||
|
public void process(final OutputStream out) throws IOException {
|
||||||
|
out.write(message.getBody().getBytes(charset));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
session.transfer(flowFile, REL_SUCCESS);
|
||||||
|
session.getProvenanceReporter().receive(flowFile, queueUrl);
|
||||||
|
|
||||||
|
getLogger().info("Successfully received {} from Amazon SQS", new Object[] {flowFile});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( autoDelete ) {
|
||||||
|
// If we want to auto-delete messages, we must fist commit the session to ensure that the data
|
||||||
|
// is persisted in NiFi's repositories.
|
||||||
|
session.commit();
|
||||||
|
|
||||||
|
final DeleteMessageBatchRequest deleteRequest = new DeleteMessageBatchRequest();
|
||||||
|
deleteRequest.setQueueUrl(queueUrl);
|
||||||
|
final List<DeleteMessageBatchRequestEntry> deleteRequestEntries = new ArrayList<>();
|
||||||
|
for ( final Message message : messages ) {
|
||||||
|
final DeleteMessageBatchRequestEntry entry = new DeleteMessageBatchRequestEntry();
|
||||||
|
entry.setId(message.getMessageId());
|
||||||
|
entry.setReceiptHandle(message.getReceiptHandle());
|
||||||
|
deleteRequestEntries.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRequest.setEntries(deleteRequestEntries);
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.deleteMessageBatch(deleteRequest);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
getLogger().error("Received {} messages from Amazon SQS but failed to delete the messages; these messages may be duplicated. Reason for deletion failure: {}", new Object[] {messages.size(), e});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* 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.aws.sqs;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.behavior.DynamicProperty;
|
||||||
|
import org.apache.nifi.annotation.behavior.SupportsBatching;
|
||||||
|
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||||
|
import org.apache.nifi.annotation.documentation.SeeAlso;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.annotation.lifecycle.OnScheduled;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processor.ProcessSession;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSClient;
|
||||||
|
import com.amazonaws.services.sqs.model.MessageAttributeValue;
|
||||||
|
import com.amazonaws.services.sqs.model.SendMessageBatchRequest;
|
||||||
|
import com.amazonaws.services.sqs.model.SendMessageBatchRequestEntry;
|
||||||
|
|
||||||
|
|
||||||
|
@SupportsBatching
|
||||||
|
@Tags({"Amazon", "AWS", "SQS", "Queue", "Put", "Publish"})
|
||||||
|
@SeeAlso({GetSQS.class, DeleteSQS.class})
|
||||||
|
@CapabilityDescription("Publishes a message to an Amazon Simple Queuing Service Queue")
|
||||||
|
@DynamicProperty(name="The name of a Message Attribute to add to the message", value="The value of the Message Attribute",
|
||||||
|
description="Allows the user to add key/value pairs as Message Attributes by adding a property whose name will become the name of "
|
||||||
|
+ "the Message Attribute and value will become the value of the Message Attribute", supportsExpressionLanguage=true)
|
||||||
|
public class PutSQS extends AbstractSQSProcessor {
|
||||||
|
|
||||||
|
public static final PropertyDescriptor DELAY = new PropertyDescriptor.Builder()
|
||||||
|
.name("Delay")
|
||||||
|
.description("The amount of time to delay the message before it becomes available to consumers")
|
||||||
|
.required(true)
|
||||||
|
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
|
||||||
|
.defaultValue("0 secs")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(
|
||||||
|
Arrays.asList(QUEUE_URL, ACCESS_KEY, SECRET_KEY, CREDENTAILS_FILE, REGION, DELAY, TIMEOUT) );
|
||||||
|
|
||||||
|
private volatile List<PropertyDescriptor> userDefinedProperties = Collections.emptyList();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
||||||
|
return new PropertyDescriptor.Builder()
|
||||||
|
.name(propertyDescriptorName)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.required(false)
|
||||||
|
.dynamic(true)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnScheduled
|
||||||
|
public void setup(final ProcessContext context) {
|
||||||
|
userDefinedProperties = new ArrayList<>();
|
||||||
|
for ( final PropertyDescriptor descriptor : context.getProperties().keySet() ) {
|
||||||
|
if ( descriptor.isDynamic() ) {
|
||||||
|
userDefinedProperties.add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrigger(final ProcessContext context, final ProcessSession session) {
|
||||||
|
FlowFile flowFile = session.get();
|
||||||
|
if ( flowFile == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long startNanos = System.nanoTime();
|
||||||
|
final AmazonSQSClient client = getClient();
|
||||||
|
final SendMessageBatchRequest request = new SendMessageBatchRequest();
|
||||||
|
final String queueUrl = context.getProperty(QUEUE_URL).evaluateAttributeExpressions(flowFile).getValue();
|
||||||
|
request.setQueueUrl(queueUrl);
|
||||||
|
|
||||||
|
final Set<SendMessageBatchRequestEntry> entries = new HashSet<>();
|
||||||
|
|
||||||
|
final SendMessageBatchRequestEntry entry = new SendMessageBatchRequestEntry();
|
||||||
|
entry.setId(flowFile.getAttribute("uuid"));
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
session.exportTo(flowFile, baos);
|
||||||
|
final String flowFileContent = baos.toString();
|
||||||
|
entry.setMessageBody(flowFileContent);
|
||||||
|
|
||||||
|
final Map<String, MessageAttributeValue> messageAttributes = new HashMap<>();
|
||||||
|
|
||||||
|
for ( final PropertyDescriptor descriptor : userDefinedProperties ) {
|
||||||
|
final MessageAttributeValue mav = new MessageAttributeValue();
|
||||||
|
mav.setDataType("String");
|
||||||
|
mav.setStringValue(context.getProperty(descriptor).evaluateAttributeExpressions(flowFile).getValue());
|
||||||
|
messageAttributes.put(descriptor.getName(), mav);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.setMessageAttributes(messageAttributes);
|
||||||
|
entry.setDelaySeconds(context.getProperty(DELAY).asTimePeriod(TimeUnit.SECONDS).intValue());
|
||||||
|
entries.add(entry);
|
||||||
|
|
||||||
|
request.setEntries(entries);
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.sendMessageBatch(request);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
getLogger().error("Failed to send messages to Amazon SQS due to {}; routing to failure", new Object[] {e});
|
||||||
|
session.transfer(flowFile, REL_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogger().info("Successfully published message to Amazon SQS for {}", new Object[] {flowFile});
|
||||||
|
session.transfer(flowFile, REL_SUCCESS);
|
||||||
|
final long transmissionMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
|
||||||
|
session.getProvenanceReporter().send(flowFile, queueUrl, transmissionMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
# 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.aws.s3.FetchS3Object
|
||||||
|
org.apache.nifi.processors.aws.s3.PutS3Object
|
||||||
|
org.apache.nifi.processors.aws.sns.PutSNS
|
||||||
|
org.apache.nifi.processors.aws.sqs.GetSQS
|
||||||
|
org.apache.nifi.processors.aws.sqs.PutSQS
|
||||||
|
org.apache.nifi.processors.aws.sqs.DeleteSQS
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.apache.nifi.processors.aws.s3;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@Ignore("For local testing only - interacts with S3 so the credentials file must be configured and all necessary buckets created")
|
||||||
|
public class TestFetchS3Object {
|
||||||
|
private final String CREDENTIALS_FILE = System.getProperty("user.home") + "/aws-credentials.properties";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGet() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new FetchS3Object());
|
||||||
|
runner.setProperty(FetchS3Object.BUCKET, "anonymous-test-bucket-00000000");
|
||||||
|
runner.setProperty(FetchS3Object.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(FetchS3Object.KEY, "folder/1.txt");
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("start", "0");
|
||||||
|
|
||||||
|
runner.enqueue(new byte[0], attrs);
|
||||||
|
runner.run(1);
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(FetchS3Object.REL_SUCCESS, 1);
|
||||||
|
final List<MockFlowFile> ffs = runner.getFlowFilesForRelationship(FetchS3Object.REL_SUCCESS);
|
||||||
|
final MockFlowFile out = ffs.iterator().next();
|
||||||
|
|
||||||
|
final byte[] expectedBytes = Files.readAllBytes(Paths.get("src/test/resources/hello.txt"));
|
||||||
|
out.assertContentEquals(new String(expectedBytes));
|
||||||
|
for ( final Map.Entry<String, String> entry : out.getAttributes().entrySet() ) {
|
||||||
|
System.out.println(entry.getKey() + " : " + entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.apache.nifi.processors.aws.s3;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.amazonaws.services.s3.model.StorageClass;
|
||||||
|
|
||||||
|
@Ignore("For local testing only - interacts with S3 so the credentials file must be configured and all necessary buckets created")
|
||||||
|
public class TestPutS3Object {
|
||||||
|
|
||||||
|
private final String CREDENTIALS_FILE = System.getProperty("user.home") + "/aws-credentials.properties";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimplePut() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutS3Object());
|
||||||
|
runner.setProperty(PutS3Object.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutS3Object.BUCKET, "test-bucket-00000000-0000-0000-0000-123456789012");
|
||||||
|
runner.setProperty(PutS3Object.EXPIRATION_RULE_ID, "Expire Quickly");
|
||||||
|
Assert.assertTrue( runner.setProperty("x-custom-prop", "hello").isValid() );
|
||||||
|
|
||||||
|
for (int i=0; i < 3; i++) {
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", String.valueOf(i) + ".txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
}
|
||||||
|
runner.run(3);
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutS3Object.REL_SUCCESS, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPutInFolder() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutS3Object());
|
||||||
|
runner.setProperty(PutS3Object.BUCKET, "test-bucket-00000000-0000-0000-0000-123456789012");
|
||||||
|
runner.setProperty(PutS3Object.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutS3Object.EXPIRATION_RULE_ID, "Expire Quickly");
|
||||||
|
Assert.assertTrue( runner.setProperty("x-custom-prop", "hello").isValid() );
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", "folder/1.txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutS3Object.REL_SUCCESS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStorageClass() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutS3Object());
|
||||||
|
runner.setProperty(PutS3Object.BUCKET, "test-bucket-00000000-0000-0000-0000-123456789012");
|
||||||
|
runner.setProperty(PutS3Object.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutS3Object.STORAGE_CLASS, StorageClass.ReducedRedundancy.name());
|
||||||
|
Assert.assertTrue( runner.setProperty("x-custom-prop", "hello").isValid() );
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", "folder/2.txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutS3Object.REL_SUCCESS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermissions() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutS3Object());
|
||||||
|
runner.setProperty(PutS3Object.BUCKET, "test-bucket-00000000-0000-0000-0000-123456789012");
|
||||||
|
runner.setProperty(PutS3Object.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutS3Object.FULL_CONTROL_USER_LIST, "28545acd76c35c7e91f8409b95fd1aa0c0914bfa1ac60975d9f48bc3c5e090b5");
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", "folder/4.txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutS3Object.REL_SUCCESS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.apache.nifi.processors.aws.sns;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@Ignore("For local testing only - interacts with S3 so the credentials file must be configured and all necessary buckets created")
|
||||||
|
public class TestPutSNS {
|
||||||
|
private final String CREDENTIALS_FILE = System.getProperty("user.home") + "/aws-credentials.properties";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPublish() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutSNS());
|
||||||
|
runner.setProperty(PutSNS.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutSNS.ARN, "arn:aws:sns:us-west-2:100515378163:test-topic-1");
|
||||||
|
assertTrue( runner.setProperty("DynamicProperty", "hello!").isValid() );
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", "1.txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutSNS.REL_SUCCESS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.apache.nifi.processors.aws.sqs;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.nifi.processors.aws.sns.PutSNS;
|
||||||
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@Ignore("For local testing only - interacts with S3 so the credentials file must be configured and all necessary buckets created")
|
||||||
|
public class TestGetSQS {
|
||||||
|
private final String CREDENTIALS_FILE = System.getProperty("user.home") + "/aws-credentials.properties";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleGet() {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new GetSQS());
|
||||||
|
runner.setProperty(PutSNS.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(GetSQS.TIMEOUT, "30 secs");
|
||||||
|
runner.setProperty(GetSQS.QUEUE_URL, "https://sqs.us-west-2.amazonaws.com/100515378163/test-queue-000000000");
|
||||||
|
|
||||||
|
runner.run(1);
|
||||||
|
|
||||||
|
final List<MockFlowFile> flowFiles = runner.getFlowFilesForRelationship(GetSQS.REL_SUCCESS);
|
||||||
|
for ( final MockFlowFile mff : flowFiles ) {
|
||||||
|
System.out.println(mff.getAttributes());
|
||||||
|
System.out.println(new String(mff.toByteArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.apache.nifi.processors.aws.sqs;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.processors.aws.sns.PutSNS;
|
||||||
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@Ignore("For local testing only - interacts with S3 so the credentials file must be configured and all necessary buckets created")
|
||||||
|
public class TestPutSQS {
|
||||||
|
private final String CREDENTIALS_FILE = System.getProperty("user.home") + "/aws-credentials.properties";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimplePut() throws IOException {
|
||||||
|
final TestRunner runner = TestRunners.newTestRunner(new PutSQS());
|
||||||
|
runner.setProperty(PutSNS.CREDENTAILS_FILE, CREDENTIALS_FILE);
|
||||||
|
runner.setProperty(PutSQS.TIMEOUT, "30 secs");
|
||||||
|
runner.setProperty(PutSQS.QUEUE_URL, "https://sqs.us-west-2.amazonaws.com/100515378163/test-queue-000000000");
|
||||||
|
Assert.assertTrue( runner.setProperty("x-custom-prop", "hello").isValid() );
|
||||||
|
|
||||||
|
final Map<String, String> attrs = new HashMap<>();
|
||||||
|
attrs.put("filename", "1.txt");
|
||||||
|
runner.enqueue(Paths.get("src/test/resources/hello.txt"), attrs);
|
||||||
|
runner.run(1);
|
||||||
|
|
||||||
|
runner.assertAllFlowFilesTransferred(PutSQS.REL_SUCCESS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Hello, World!!
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?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-aws-bundle</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>nifi-aws-processors</module>
|
||||||
|
<module>nifi-aws-nar</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk</artifactId>
|
||||||
|
<version>1.9.24</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
</project>
|
|
@ -32,14 +32,6 @@
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.apache.nifi</groupId>
|
||||||
<artifactId>nifi-properties</artifactId>
|
<artifactId>nifi-properties</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.apache.nifi</groupId>
|
||||||
<artifactId>nifi-processor-utils</artifactId>
|
<artifactId>nifi-processor-utils</artifactId>
|
||||||
|
|
|
@ -26,7 +26,6 @@ import javax.xml.stream.XMLOutputFactory;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.nifi.annotation.behavior.DynamicProperties;
|
import org.apache.nifi.annotation.behavior.DynamicProperties;
|
||||||
import org.apache.nifi.annotation.behavior.DynamicProperty;
|
import org.apache.nifi.annotation.behavior.DynamicProperty;
|
||||||
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||||
|
@ -212,13 +211,23 @@ public class HtmlDocumentationWriter implements DocumentationWriter {
|
||||||
xmlStreamWriter.writeEndElement();
|
xmlStreamWriter.writeEndElement();
|
||||||
xmlStreamWriter.writeStartElement("p");
|
xmlStreamWriter.writeStartElement("p");
|
||||||
if (tags != null) {
|
if (tags != null) {
|
||||||
final String tagString = StringUtils.join(tags.value(), ", ");
|
final String tagString = join(tags.value(), ", ");
|
||||||
xmlStreamWriter.writeCharacters(tagString);
|
xmlStreamWriter.writeCharacters(tagString);
|
||||||
} else {
|
} else {
|
||||||
xmlStreamWriter.writeCharacters("None.");
|
xmlStreamWriter.writeCharacters("None.");
|
||||||
}
|
}
|
||||||
xmlStreamWriter.writeEndElement();
|
xmlStreamWriter.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String join(final String[] toJoin, final String delimiter) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i=0; i < toJoin.length; i++) {
|
||||||
|
sb.append(toJoin[i]);
|
||||||
|
if ( i < toJoin.length - 1 ) {
|
||||||
|
sb.append(delimiter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.List;
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.nifi.annotation.behavior.DynamicRelationship;
|
import org.apache.nifi.annotation.behavior.DynamicRelationship;
|
||||||
import org.apache.nifi.annotation.behavior.ReadsAttribute;
|
import org.apache.nifi.annotation.behavior.ReadsAttribute;
|
||||||
import org.apache.nifi.annotation.behavior.ReadsAttributes;
|
import org.apache.nifi.annotation.behavior.ReadsAttributes;
|
||||||
|
@ -67,6 +66,13 @@ public class HtmlProcessorDocumentationWriter extends HtmlDocumentationWriter {
|
||||||
handleWritesAttributes(xmlStreamWriter, processor);
|
handleWritesAttributes(xmlStreamWriter, processor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String defaultIfBlank(final String test, final String defaultValue) {
|
||||||
|
if ( test == null || test.trim().isEmpty() ) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes out just the attributes that are being read in a table form.
|
* Writes out just the attributes that are being read in a table form.
|
||||||
*
|
*
|
||||||
|
@ -91,10 +97,10 @@ public class HtmlProcessorDocumentationWriter extends HtmlDocumentationWriter {
|
||||||
for (ReadsAttribute attribute : attributesRead) {
|
for (ReadsAttribute attribute : attributesRead) {
|
||||||
xmlStreamWriter.writeStartElement("tr");
|
xmlStreamWriter.writeStartElement("tr");
|
||||||
writeSimpleElement(xmlStreamWriter, "td",
|
writeSimpleElement(xmlStreamWriter, "td",
|
||||||
StringUtils.defaultIfBlank(attribute.attribute(), "Not Specified"));
|
defaultIfBlank(attribute.attribute(), "Not Specified"));
|
||||||
// TODO allow for HTML characters here.
|
// TODO allow for HTML characters here.
|
||||||
writeSimpleElement(xmlStreamWriter, "td",
|
writeSimpleElement(xmlStreamWriter, "td",
|
||||||
StringUtils.defaultIfBlank(attribute.description(), "Not Specified"));
|
defaultIfBlank(attribute.description(), "Not Specified"));
|
||||||
xmlStreamWriter.writeEndElement();
|
xmlStreamWriter.writeEndElement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -129,10 +135,10 @@ public class HtmlProcessorDocumentationWriter extends HtmlDocumentationWriter {
|
||||||
for (WritesAttribute attribute : attributesRead) {
|
for (WritesAttribute attribute : attributesRead) {
|
||||||
xmlStreamWriter.writeStartElement("tr");
|
xmlStreamWriter.writeStartElement("tr");
|
||||||
writeSimpleElement(xmlStreamWriter, "td",
|
writeSimpleElement(xmlStreamWriter, "td",
|
||||||
StringUtils.defaultIfBlank(attribute.attribute(), "Not Specified"));
|
defaultIfBlank(attribute.attribute(), "Not Specified"));
|
||||||
// TODO allow for HTML characters here.
|
// TODO allow for HTML characters here.
|
||||||
writeSimpleElement(xmlStreamWriter, "td",
|
writeSimpleElement(xmlStreamWriter, "td",
|
||||||
StringUtils.defaultIfBlank(attribute.description(), "Not Specified"));
|
defaultIfBlank(attribute.description(), "Not Specified"));
|
||||||
xmlStreamWriter.writeEndElement();
|
xmlStreamWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
xmlStreamWriter.writeEndElement();
|
xmlStreamWriter.writeEndElement();
|
||||||
|
|
|
@ -30,9 +30,17 @@ import org.apache.nifi.reporting.ReportingTask;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
|
import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class HtmlDocumentationWriterTest {
|
public class HtmlDocumentationWriterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoin() {
|
||||||
|
assertEquals("a, b, c", HtmlDocumentationWriter.join(new String[] {"a", "b", "c"}, ", "));
|
||||||
|
assertEquals("a, b", HtmlDocumentationWriter.join(new String[] {"a", "b"}, ", "));
|
||||||
|
assertEquals("a", HtmlDocumentationWriter.join(new String[] {"a"}, ", "));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDocumentControllerService() throws InitializationException, IOException {
|
public void testDocumentControllerService() throws InitializationException, IOException {
|
||||||
|
|
||||||
|
|
|
@ -116,12 +116,23 @@ public class StandardRepositoryRecord implements RepositoryRecord {
|
||||||
|
|
||||||
public void setWorking(final FlowFileRecord flowFile, final String attributeKey, final String attributeValue) {
|
public void setWorking(final FlowFileRecord flowFile, final String attributeKey, final String attributeValue) {
|
||||||
workingFlowFileRecord = flowFile;
|
workingFlowFileRecord = flowFile;
|
||||||
updatedAttributes.put(attributeKey, attributeValue);
|
|
||||||
|
// If setting attribute to same value as original, don't add to updated attributes
|
||||||
|
final String currentValue = originalAttributes.get(attributeKey);
|
||||||
|
if ( currentValue == null || !currentValue.equals(attributeValue) ) {
|
||||||
|
updatedAttributes.put(attributeKey, attributeValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWorking(final FlowFileRecord flowFile, final Map<String, String> updatedAttribs) {
|
public void setWorking(final FlowFileRecord flowFile, final Map<String, String> updatedAttribs) {
|
||||||
workingFlowFileRecord = flowFile;
|
workingFlowFileRecord = flowFile;
|
||||||
updatedAttributes.putAll(updatedAttribs);
|
|
||||||
|
for ( final Map.Entry<String, String> entry : updatedAttribs.entrySet() ) {
|
||||||
|
final String currentValue = originalAttributes.get(entry.getKey());
|
||||||
|
if ( currentValue == null || !currentValue.equals(entry.getValue()) ) {
|
||||||
|
updatedAttributes.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -107,6 +107,6 @@ public class ContinuallyRunConnectableTask implements Callable<Boolean> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false; // do not yield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,7 @@ public class StandardRemoteGroupPort extends RemoteGroupPort {
|
||||||
this.targetRunning.set(false);
|
this.targetRunning.set(false);
|
||||||
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port is not in a valid state", this, url);
|
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port is not in a valid state", this, url);
|
||||||
logger.error(message);
|
logger.error(message);
|
||||||
|
session.rollback();
|
||||||
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
||||||
return;
|
return;
|
||||||
} catch (final UnknownPortException e) {
|
} catch (final UnknownPortException e) {
|
||||||
|
@ -178,21 +179,24 @@ public class StandardRemoteGroupPort extends RemoteGroupPort {
|
||||||
this.targetExists.set(false);
|
this.targetExists.set(false);
|
||||||
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port no longer exists", this, url);
|
final String message = String.format("%s failed to communicate with %s because the remote instance indicates that the port no longer exists", this, url);
|
||||||
logger.error(message);
|
logger.error(message);
|
||||||
|
session.rollback();
|
||||||
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
||||||
return;
|
return;
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
|
context.yield();
|
||||||
final String message = String.format("%s failed to communicate with %s due to %s", this, url, e.toString());
|
final String message = String.format("%s failed to communicate with %s due to %s", this, url, e.toString());
|
||||||
logger.error(message);
|
logger.error(message);
|
||||||
if ( logger.isDebugEnabled() ) {
|
if ( logger.isDebugEnabled() ) {
|
||||||
logger.error("", e);
|
logger.error("", e);
|
||||||
}
|
}
|
||||||
|
session.rollback();
|
||||||
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
remoteGroup.getEventReporter().reportEvent(Severity.ERROR, CATEGORY, message);
|
||||||
session.rollback();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( transaction == null ) {
|
if ( transaction == null ) {
|
||||||
logger.debug("{} Unable to create transaction to communicate with; all peers must be penalized, so yielding context", this);
|
logger.debug("{} Unable to create transaction to communicate with; all peers must be penalized, so yielding context", this);
|
||||||
|
session.rollback();
|
||||||
context.yield();
|
context.yield();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,8 +121,14 @@ public class StandardNiFiContentAccess implements ContentAccess {
|
||||||
final String rawDirection = StringUtils.substringAfterLast(eventDetails, "/content/");
|
final String rawDirection = StringUtils.substringAfterLast(eventDetails, "/content/");
|
||||||
|
|
||||||
// get the content type
|
// get the content type
|
||||||
final Long eventId = Long.parseLong(rawEventId);
|
final Long eventId;
|
||||||
final ContentDirection direction = ContentDirection.valueOf(rawDirection.toUpperCase());
|
final ContentDirection direction;
|
||||||
|
try {
|
||||||
|
eventId = Long.parseLong(rawEventId);
|
||||||
|
direction = ContentDirection.valueOf(rawDirection.toUpperCase());
|
||||||
|
} catch (final IllegalArgumentException iae) {
|
||||||
|
throw new IllegalArgumentException("The specified data reference URI is not valid.");
|
||||||
|
}
|
||||||
return serviceFacade.getContent(eventId, request.getDataUri(), direction);
|
return serviceFacade.getContent(eventId, request.getDataUri(), direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,7 @@ public class AdministrationExceptionMapper implements ExceptionMapper<Administra
|
||||||
@Override
|
@Override
|
||||||
public Response toResponse(AdministrationException exception) {
|
public Response toResponse(AdministrationException exception) {
|
||||||
// log the error
|
// log the error
|
||||||
logger.info(String.format("%s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR));
|
logger.error(String.format("%s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR), exception);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(StringUtils.EMPTY, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate the response
|
// generate the response
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).type("text/plain").build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).type("text/plain").build();
|
||||||
|
|
|
@ -35,11 +35,7 @@ public class ClusterExceptionMapper implements ExceptionMapper<ClusterException>
|
||||||
@Override
|
@Override
|
||||||
public Response toResponse(ClusterException exception) {
|
public Response toResponse(ClusterException exception) {
|
||||||
// log the error
|
// log the error
|
||||||
logger.info(String.format("%s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR));
|
logger.error(String.format("%s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR), exception);
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(StringUtils.EMPTY, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).type("text/plain").build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).type("text/plain").build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.web.api.config;
|
||||||
|
|
||||||
|
import com.sun.jersey.api.NotFoundException;
|
||||||
|
import com.sun.jersey.api.Responses;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
import org.apache.nifi.util.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps not found exceptions into client responses.
|
||||||
|
*/
|
||||||
|
@Provider
|
||||||
|
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(NotFoundExceptionMapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(NotFoundException exception) {
|
||||||
|
// log the error
|
||||||
|
logger.info(String.format("%s. Returning %s response.", exception, Response.Status.NOT_FOUND));
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(StringUtils.EMPTY, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Responses.notFound().entity("The specified resource could not be found.").type("text/plain").build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,8 +34,7 @@ public class ThrowableMapper implements ExceptionMapper<Throwable> {
|
||||||
@Override
|
@Override
|
||||||
public Response toResponse(Throwable exception) {
|
public Response toResponse(Throwable exception) {
|
||||||
// log the error
|
// log the error
|
||||||
logger.error(String.format("An unexpected error has occurred: %s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR));
|
logger.error(String.format("An unexpected error has occurred: %s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR), exception);
|
||||||
logger.error(StringUtils.EMPTY, exception);
|
|
||||||
|
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("An unexpected error has occurred. Please check the logs for additional details.").type("text/plain").build();
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("An unexpected error has occurred. Please check the logs for additional details.").type("text/plain").build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,7 @@
|
||||||
<bean class="org.apache.nifi.web.api.config.NodeReconnectionExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.NodeReconnectionExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.PrimaryRoleAssignmentExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.PrimaryRoleAssignmentExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.ResourceNotFoundExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.ResourceNotFoundExceptionMapper" scope="singleton"/>
|
||||||
|
<bean class="org.apache.nifi.web.api.config.NotFoundExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.UnknownNodeExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.UnknownNodeExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.ValidationExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.ValidationExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.WebApplicationExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.WebApplicationExceptionMapper" scope="singleton"/>
|
||||||
|
|
|
@ -68,10 +68,21 @@ public class ContentViewerController extends HttpServlet {
|
||||||
final ServletContext servletContext = request.getServletContext();
|
final ServletContext servletContext = request.getServletContext();
|
||||||
final ContentAccess contentAccess = (ContentAccess) servletContext.getAttribute("nifi-content-access");
|
final ContentAccess contentAccess = (ContentAccess) servletContext.getAttribute("nifi-content-access");
|
||||||
|
|
||||||
|
final ContentRequestContext contentRequest = getContentRequest(request);
|
||||||
|
if (contentRequest.getDataUri() == null) {
|
||||||
|
request.setAttribute("title", "Error");
|
||||||
|
request.setAttribute("messages", "The data reference must be specified.");
|
||||||
|
|
||||||
|
// forward to the error page
|
||||||
|
final ServletContext viewerContext = servletContext.getContext("/nifi");
|
||||||
|
viewerContext.getRequestDispatcher("/message").forward(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get the content
|
// get the content
|
||||||
final DownloadableContent downloadableContent;
|
final DownloadableContent downloadableContent;
|
||||||
try {
|
try {
|
||||||
downloadableContent = contentAccess.getContent(getContentRequest(request));
|
downloadableContent = contentAccess.getContent(contentRequest);
|
||||||
} catch (final ResourceNotFoundException rnfe) {
|
} catch (final ResourceNotFoundException rnfe) {
|
||||||
request.setAttribute("title", "Error");
|
request.setAttribute("title", "Error");
|
||||||
request.setAttribute("messages", "Unable to find the specified content");
|
request.setAttribute("messages", "Unable to find the specified content");
|
||||||
|
@ -138,9 +149,6 @@ public class ContentViewerController extends HttpServlet {
|
||||||
final String mimeType = mediatype.toString();
|
final String mimeType = mediatype.toString();
|
||||||
|
|
||||||
// add attributes needed for the header
|
// add attributes needed for the header
|
||||||
final StringBuffer requestUrl = request.getRequestURL();
|
|
||||||
request.setAttribute("requestUrl", requestUrl.toString());
|
|
||||||
request.setAttribute("dataRef", request.getParameter("ref"));
|
|
||||||
request.setAttribute("filename", downloadableContent.getFilename());
|
request.setAttribute("filename", downloadableContent.getFilename());
|
||||||
request.setAttribute("contentType", mimeType);
|
request.setAttribute("contentType", mimeType);
|
||||||
|
|
||||||
|
@ -148,8 +156,6 @@ public class ContentViewerController extends HttpServlet {
|
||||||
request.getRequestDispatcher("/WEB-INF/jsp/header.jsp").include(request, response);
|
request.getRequestDispatcher("/WEB-INF/jsp/header.jsp").include(request, response);
|
||||||
|
|
||||||
// remove the attributes needed for the header
|
// remove the attributes needed for the header
|
||||||
request.removeAttribute("requestUrl");
|
|
||||||
request.removeAttribute("dataRef");
|
|
||||||
request.removeAttribute("filename");
|
request.removeAttribute("filename");
|
||||||
request.removeAttribute("contentType");
|
request.removeAttribute("contentType");
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var $$ = $.noConflict(true);
|
var $$ = $.noConflict(true);
|
||||||
$$(document).ready(function () {
|
$$(document).ready(function () {
|
||||||
var url = '${requestUrl}';
|
var url = $$('#requestUrl').text();
|
||||||
var ref = '${param.ref}';
|
var ref = $$('#ref').text();
|
||||||
|
|
||||||
// create the parameters
|
// create the parameters
|
||||||
var params = {
|
var params = {
|
||||||
|
@ -40,14 +40,14 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
// include the cluster node if appropriate
|
// include the cluster node if appropriate
|
||||||
var clusterNodeId = '${param.clusterNodeId}';
|
var clusterNodeId = $$('#clusterNodeId').text();
|
||||||
if (clusterNodeId !== null && clusterNodeId !== '') {
|
if (clusterNodeId !== '') {
|
||||||
params['clusterNodeId'] = clusterNodeId;
|
params['clusterNodeId'] = clusterNodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the appropriate mode to select initially
|
// determine the appropriate mode to select initially
|
||||||
var initialMode = '${param.mode}';
|
var initialMode = $$('#mode').text();
|
||||||
if (initialMode === null && initialMode === '') {
|
if (initialMode === '') {
|
||||||
initialMode = 'Original';
|
initialMode = 'Original';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +85,12 @@
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="message-pane">
|
<body class="message-pane">
|
||||||
|
<span id="ref" class="hidden"><%= org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("ref")) %></span>
|
||||||
|
<span id="clusterNodeId" class="hidden"><%= request.getParameter("clusterNodeId") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("clusterNodeId")) %></span>
|
||||||
|
<span id="mode" class="hidden"><%= request.getParameter("mode") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("mode")) %></span>
|
||||||
|
<span id="requestUrl" class="hidden"><%= org.apache.nifi.util.EscapeUtils.escapeHtml(request.getRequestURL().toString()) %></span>
|
||||||
<div id="view-as-label">View as</div>
|
<div id="view-as-label">View as</div>
|
||||||
<div id="view-as" class="pointer button-normal"></div>
|
<div id="view-as" class="pointer button-normal"></div>
|
||||||
<div id="content-filename"><span class="content-label">filename</span>${filename}</div>
|
<div id="content-filename"><span class="content-label">filename</span><%= request.getAttribute("filename") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getAttribute("filename").toString()) %></div>
|
||||||
<div id="content-type"><span class="content-label">content type</span>${contentType}</div>
|
<div id="content-type"><span class="content-label">content type</span><%= request.getAttribute("contentType") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getAttribute("contentType").toString()) %></div>
|
||||||
<div class="message-pane-message-box">
|
<div class="message-pane-message-box">
|
|
@ -29,4 +29,4 @@
|
||||||
<input type="hidden" name="caption" value="" />
|
<input type="hidden" name="caption" value="" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="trancation-message">Showing up to 1.5kb</div>
|
<div id="truncation-message">Showing up to 1.5 KB</div>
|
|
@ -87,7 +87,7 @@
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#trancation-message {
|
#truncation-message {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 100px;
|
left: 100px;
|
||||||
bottom: 35px;
|
bottom: 35px;
|
||||||
|
|
|
@ -148,7 +148,7 @@ $(document).ready(function () {
|
||||||
|
|
||||||
$("table", div).addClass("hexviewerwindow_table");
|
$("table", div).addClass("hexviewerwindow_table");
|
||||||
$("table", div).append("<tr></tr>").addClass("hexviewerwindow");
|
$("table", div).append("<tr></tr>").addClass("hexviewerwindow");
|
||||||
$("table tr:last", div).append("<td>" + (decimal_offset ? ("00000000"+offset).slice(-8) : "0x" + dec_to_hex8(offset)) + "</td>");
|
$("table tr:last", div).append("<td>" + escapeHtml((decimal_offset ? ("00000000"+offset).slice(-8) : "0x" + dec_to_hex8(offset))) + "</td>");
|
||||||
$("table tr td:last", div).addClass("hexviewerwindow_offset");
|
$("table tr td:last", div).addClass("hexviewerwindow_offset");
|
||||||
|
|
||||||
var runlen = 0;
|
var runlen = 0;
|
||||||
|
@ -162,7 +162,7 @@ $(document).ready(function () {
|
||||||
num += dec2_to_hex(line_data.charCodeAt(i+j));
|
num += dec2_to_hex(line_data.charCodeAt(i+j));
|
||||||
}
|
}
|
||||||
|
|
||||||
$("table tr:last", div).append("<td>" + (hide_0x ? "" : "0x") + num + "</td>");
|
$("table tr:last", div).append("<td>" + escapeHtml((hide_0x ? "" : "0x") + num) + "</td>");
|
||||||
|
|
||||||
apply_highlights(offset+i);
|
apply_highlights(offset+i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,18 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.apache.nifi</groupId>
|
||||||
<artifactId>nifi-nar-utils</artifactId>
|
<artifactId>nifi-nar-utils</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-utils</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet.jsp</groupId>
|
<groupId>javax.servlet.jsp</groupId>
|
||||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<body id="documentation-body">
|
<body id="documentation-body">
|
||||||
<div id="banner-header" class="main-banner-header"></div>
|
<div id="banner-header" class="main-banner-header"></div>
|
||||||
<div id="banner-footer" class="main-banner-footer"></div>
|
<div id="banner-footer" class="main-banner-footer"></div>
|
||||||
<span id="initial-selection" style="display: none;">${param.select}</span>
|
<span id="initial-selection" style="display: none;"><%= request.getParameter("select") == null ? "" : org.apache.nifi.util.EscapeUtils.escapeHtml(request.getParameter("select")) %></span>
|
||||||
<div id="documentation-header" class="documentation-header">
|
<div id="documentation-header" class="documentation-header">
|
||||||
<div id="nf-title">NiFi Documentation</div>
|
<div id="nf-title">NiFi Documentation</div>
|
||||||
<div id="nf-version"></div>
|
<div id="nf-version"></div>
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global top */
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
var isUndefined = function (obj) {
|
var isUndefined = function (obj) {
|
||||||
|
@ -139,7 +142,7 @@ $(document).ready(function () {
|
||||||
if (isDefinedAndNotNull(response.banners)) {
|
if (isDefinedAndNotNull(response.banners)) {
|
||||||
if (isDefinedAndNotNull(response.banners.headerText) && response.banners.headerText !== '') {
|
if (isDefinedAndNotNull(response.banners.headerText) && response.banners.headerText !== '') {
|
||||||
// update the header text
|
// update the header text
|
||||||
var bannerHeader = $('#banner-header').html(response.banners.headerText).show();
|
var bannerHeader = $('#banner-header').text(response.banners.headerText).show();
|
||||||
|
|
||||||
// show the banner
|
// show the banner
|
||||||
var updateTop = function (elementId) {
|
var updateTop = function (elementId) {
|
||||||
|
@ -155,7 +158,7 @@ $(document).ready(function () {
|
||||||
|
|
||||||
if (isDefinedAndNotNull(response.banners.footerText) && response.banners.footerText !== '') {
|
if (isDefinedAndNotNull(response.banners.footerText) && response.banners.footerText !== '') {
|
||||||
// update the footer text and show it
|
// update the footer text and show it
|
||||||
var bannerFooter = $('#banner-footer').html(response.banners.footerText).show();
|
var bannerFooter = $('#banner-footer').text(response.banners.footerText).show();
|
||||||
|
|
||||||
var updateBottom = function (elementId) {
|
var updateBottom = function (elementId) {
|
||||||
var element = $('#' + elementId);
|
var element = $('#' + elementId);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue