mirror of https://github.com/apache/nifi.git
Initial code contribution
This commit is contained in:
commit
4d998c12c9
|
@ -0,0 +1,9 @@
|
||||||
|
target
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
nbactions.xml
|
||||||
|
|
||||||
|
# Intellij
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*.iws
|
|
@ -0,0 +1,15 @@
|
||||||
|
Apache NiFi is an effort undergoing incubation at the Apache Software
|
||||||
|
Foundation (ASF), sponsored by the Apache Incubator PMC.
|
||||||
|
|
||||||
|
Incubation is required of all newly accepted projects until a further review
|
||||||
|
indicates that the infrastructure, communications, and decision making process
|
||||||
|
have stabilized in a manner consistent with other successful ASF projects.
|
||||||
|
|
||||||
|
While incubation status is not necessarily a reflection of the completeness
|
||||||
|
or stability of the code, it does indicate that the project has yet to be
|
||||||
|
fully endorsed by the ASF.
|
||||||
|
|
||||||
|
For more information about the incubation status of the Apache NiFi project
|
||||||
|
you can go to the following page:
|
||||||
|
|
||||||
|
http://nifi.incubator.apache.org/
|
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed 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.
|
|
@ -0,0 +1,7 @@
|
||||||
|
Apache NiFi
|
||||||
|
Copyright 2014 The Apache Software Foundation
|
||||||
|
|
||||||
|
This product includes software developed at
|
||||||
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
|
||||||
|
Please see LICENSE for additional copyright and licensing information.
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Apache NiFi
|
||||||
|
|
||||||
|
Apache NiFi is a dataflow system based on the concepts of flow-based programming. It is currently apart of the Apache Incubator.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Features](#features)
|
||||||
|
- [Getting Started](#getting-started)
|
||||||
|
- [Getting Help](#getting-help)
|
||||||
|
- [Requirements](#requirements)
|
||||||
|
- [License](#license)
|
||||||
|
- [Disclaimer](#disclaimer)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Apache NiFi supports powerful and scalable directed graphs of data routing, transformation, and system mediation logic. Some of the high-level capabilities and objectives of Apache NiFi include:
|
||||||
|
|
||||||
|
- Web-based user interface for seamless experience between design, control, feedback, and monitoring of data flows
|
||||||
|
- Highly configurable along several dimensions of quality of service such as loss tolerant versus guaranteed delivery, low latency versus high throughput, and priority based queuing
|
||||||
|
- Fine-grained data provenance for all data received, forked, joined, cloned, modified, sent, and ultimately dropped as data reaches its configured end-state
|
||||||
|
- Component-based extension model along well defined interfaces enabling rapid development and effective testing
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Execute <nifi install dir>/bin/nifi.sh
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
If you have questions, you can reach out to our mailing list: dev@nifi.incubator.apache.org
|
||||||
|
([archive](http://mail-archives.apache.org/mod_mbox/incubator-nifi-dev)).
|
||||||
|
We're also often available in IRC: #nifi on
|
||||||
|
[irc.freenode.net](http://webchat.freenode.net/?channels=#nifi).
|
||||||
|
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
* JDK 1.7 or higher
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Except as otherwise noted this software is licensed under the
|
||||||
|
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
|
||||||
|
|
||||||
|
Licensed 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.
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
Apache NiFi is an effort undergoing incubation at the Apache Software
|
||||||
|
Foundation (ASF), sponsored by the Apache Incubator PMC.
|
||||||
|
|
||||||
|
Incubation is required of all newly accepted projects until a further review
|
||||||
|
indicates that the infrastructure, communications, and decision making process
|
||||||
|
have stabilized in a manner consistent with other successful ASF projects.
|
||||||
|
|
||||||
|
While incubation status is not necessarily a reflection of the completeness
|
||||||
|
or stability of the code, it does indicate that the project has yet to be
|
||||||
|
fully endorsed by the ASF.
|
|
@ -0,0 +1,485 @@
|
||||||
|
<?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/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nifi</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<name>NiFi Release</name>
|
||||||
|
<description>This is the assembly for the Main Standard Release of NiFi</description>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>unpack-shared-resources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>unpack-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
|
||||||
|
<includeArtifactIds>nifi-resources</includeArtifactIds>
|
||||||
|
<includeGroupIds>org.apache.nifi</includeGroupIds>
|
||||||
|
<excludeTransitive>false</excludeTransitive>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/dependencies.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>1.3.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<executable>${project.build.directory}/${project.artifactId}-${project.version}-${nifi.assembly.id}.dir/${nifi.executable}</executable>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${basedir}/src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.build.directory}/generated-resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</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>
|
||||||
|
<version>${org.slf4j.version}</version>
|
||||||
|
<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>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-runtime</artifactId>
|
||||||
|
<version>${framework.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-resources</artifactId>
|
||||||
|
<version>${framework.version}</version>
|
||||||
|
<classifier>resources</classifier>
|
||||||
|
<scope>provided</scope> <!-- Provided - we don't want the zip in the libs -->
|
||||||
|
<type>zip</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-framework-nar</artifactId>
|
||||||
|
<version>${framework.version}</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>volatile-provenance-repository-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>persistent-provenance-repository-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>standard-services-api-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>ssl-context-service-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>distributed-cache-services-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-standard-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-jetty-bundle</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>update-attribute-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>monitor-threshold-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>hadoop-libraries-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>hadoop-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>
|
||||||
|
<!-- <dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>execute-script-nar</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<type>nar</type>
|
||||||
|
</dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<framework.version>0.0.1-SNAPSHOT</framework.version>
|
||||||
|
|
||||||
|
<!--Wrapper Properties-->
|
||||||
|
<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.initial.permgen.size.mb>128</nifi.initial.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.maxfiles>10</nifi.wrapper.logfile.maxfiles>
|
||||||
|
|
||||||
|
<!-- nifi.properties: core properties -->
|
||||||
|
<nifi.flowcontroller.autoResumeState>true</nifi.flowcontroller.autoResumeState>
|
||||||
|
<nifi.flowcontroller.graceful.shutdown.period>10 sec</nifi.flowcontroller.graceful.shutdown.period>
|
||||||
|
<nifi.flowservice.writedelay.interval>500 ms</nifi.flowservice.writedelay.interval>
|
||||||
|
<nifi.administrative.yield.duration>30 sec</nifi.administrative.yield.duration>
|
||||||
|
|
||||||
|
<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.reporting.task.configuration.file>./conf/reporting-tasks.xml</nifi.reporting.task.configuration.file>
|
||||||
|
<nifi.controller.service.configuration.file>./conf/controller-services.xml</nifi.controller.service.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.database.directory>./database_repository</nifi.database.directory>
|
||||||
|
|
||||||
|
<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.partitions>256</nifi.flowfile.repository.partitions>
|
||||||
|
<nifi.flowfile.repository.checkpoint.interval>2 mins</nifi.flowfile.repository.checkpoint.interval>
|
||||||
|
<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.queue.swap.threshold>20000</nifi.queue.swap.threshold>
|
||||||
|
<nifi.swap.storage.directory>./flowfile_repository/swap</nifi.swap.storage.directory>
|
||||||
|
<nifi.swap.in.period>5 sec</nifi.swap.in.period>
|
||||||
|
<nifi.swap.in.threads>1</nifi.swap.in.threads>
|
||||||
|
<nifi.swap.out.period>5 sec</nifi.swap.out.period>
|
||||||
|
<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.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.repository.directory.default>./content_repository</nifi.content.repository.directory.default>
|
||||||
|
<nifi.content.repository.archive.max.retention.period />
|
||||||
|
<nifi.content.repository.archive.max.usage.percentage />
|
||||||
|
<nifi.content.repository.archive.enabled>false</nifi.content.repository.archive.enabled>
|
||||||
|
<nifi.content.repository.always.sync>false</nifi.content.repository.always.sync>
|
||||||
|
<nifi.content.viewer.url />
|
||||||
|
|
||||||
|
|
||||||
|
<nifi.restore.directory />
|
||||||
|
<nifi.ui.banner.text></nifi.ui.banner.text>
|
||||||
|
<nifi.ui.autorefresh.interval>30 sec</nifi.ui.autorefresh.interval>
|
||||||
|
<nifi.nar.library.directory>./lib</nifi.nar.library.directory>
|
||||||
|
<nifi.nar.working.directory>./work/nar/</nifi.nar.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.provider>BC</nifi.sensitive.props.provider>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- persistent provenance repository properties -->
|
||||||
|
<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.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.rollover.time>5 mins</nifi.provenance.repository.rollover.time>
|
||||||
|
<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.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.attributes />
|
||||||
|
<nifi.provenance.repository.index.shard.size>500 MB</nifi.provenance.repository.index.shard.size>
|
||||||
|
<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 -->
|
||||||
|
<nifi.provenance.repository.buffer.size>100000</nifi.provenance.repository.buffer.size>
|
||||||
|
|
||||||
|
<!-- 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.buffer.size>288</nifi.components.status.repository.buffer.size>
|
||||||
|
<nifi.components.status.snapshot.frequency>5 mins</nifi.components.status.snapshot.frequency>
|
||||||
|
|
||||||
|
<!-- nifi.properties: web properties -->
|
||||||
|
<nifi.web.war.directory>./lib</nifi.web.war.directory>
|
||||||
|
<nifi.web.http.host />
|
||||||
|
<nifi.web.http.port>8080</nifi.web.http.port>
|
||||||
|
<nifi.web.https.host />
|
||||||
|
<nifi.web.https.port />
|
||||||
|
<nifi.jetty.work.dir>./work/jetty</nifi.jetty.work.dir>
|
||||||
|
|
||||||
|
<!-- nifi.properties: security properties -->
|
||||||
|
<nifi.security.keystore />
|
||||||
|
<nifi.security.keystoreType />
|
||||||
|
<nifi.security.keystorePasswd />
|
||||||
|
<nifi.security.keyPasswd />
|
||||||
|
<nifi.security.truststore />
|
||||||
|
<nifi.security.truststoreType />
|
||||||
|
<nifi.security.truststorePasswd />
|
||||||
|
<nifi.security.needClientAuth />
|
||||||
|
<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.authority.provider>file-provider</nifi.security.user.authority.provider>
|
||||||
|
<nifi.security.x509.principal.extractor />
|
||||||
|
<nifi.security.support.new.account.requests />
|
||||||
|
<nifi.security.ocsp.responder.url />
|
||||||
|
<nifi.security.ocsp.responder.certificate />
|
||||||
|
|
||||||
|
<!-- nifi.properties: cluster common properties (cluster manager and nodes must have same values) -->
|
||||||
|
<nifi.cluster.protocol.heartbeat.interval>5 sec</nifi.cluster.protocol.heartbeat.interval>
|
||||||
|
<nifi.cluster.protocol.is.secure>false</nifi.cluster.protocol.is.secure>
|
||||||
|
<nifi.cluster.protocol.socket.timeout>30 sec</nifi.cluster.protocol.socket.timeout>
|
||||||
|
<nifi.cluster.protocol.connection.handshake.timeout>45 sec</nifi.cluster.protocol.connection.handshake.timeout>
|
||||||
|
<nifi.cluster.protocol.use.multicast>false</nifi.cluster.protocol.use.multicast>
|
||||||
|
<nifi.cluster.protocol.multicast.address />
|
||||||
|
<nifi.cluster.protocol.multicast.port />
|
||||||
|
<nifi.cluster.protocol.multicast.service.broadcast.delay>500 ms</nifi.cluster.protocol.multicast.service.broadcast.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.cluster.is.node>false</nifi.cluster.is.node>
|
||||||
|
<nifi.cluster.node.address />
|
||||||
|
<nifi.cluster.node.protocol.port />
|
||||||
|
<nifi.cluster.node.protocol.threads>2</nifi.cluster.node.protocol.threads>
|
||||||
|
<nifi.cluster.node.unicast.manager.address />
|
||||||
|
<nifi.cluster.node.unicast.manager.protocol.port />
|
||||||
|
|
||||||
|
<!-- nifi.properties: cluster manager properties (only configure for cluster manager) -->
|
||||||
|
<nifi.cluster.is.manager>false</nifi.cluster.is.manager>
|
||||||
|
<nifi.cluster.manager.address />
|
||||||
|
<nifi.cluster.manager.protocol.port />
|
||||||
|
<nifi.cluster.manager.node.firewall.file />
|
||||||
|
<nifi.cluster.manager.node.event.history.size>10</nifi.cluster.manager.node.event.history.size>
|
||||||
|
<nifi.cluster.manager.node.api.connection.timeout>30 sec</nifi.cluster.manager.node.api.connection.timeout>
|
||||||
|
<nifi.cluster.manager.node.api.read.timeout>30 sec</nifi.cluster.manager.node.api.read.timeout>
|
||||||
|
<nifi.cluster.manager.node.api.request.threads>10</nifi.cluster.manager.node.api.request.threads>
|
||||||
|
<nifi.cluster.manager.flow.retrieval.delay>5 sec</nifi.cluster.manager.flow.retrieval.delay>
|
||||||
|
<nifi.cluster.manager.protocol.threads>10</nifi.cluster.manager.protocol.threads>
|
||||||
|
<nifi.cluster.manager.safemode.duration>0 sec</nifi.cluster.manager.safemode.duration>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Properties to execute nifi using Maven. It is assumed that the assembly has a
|
||||||
|
format of type 'dir' so that the executable can be referenced in a defined location.
|
||||||
|
-->
|
||||||
|
<nifi.assembly.id>bin</nifi.assembly.id>
|
||||||
|
<nifi.executable>${project.artifactId}-${project.version}/bin/${project.artifactId}</nifi.executable>
|
||||||
|
|
||||||
|
</properties>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>standard-rpm</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>rpm-maven-plugin</artifactId>
|
||||||
|
<version>2.0.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>rpm</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<projversion>${project.version}</projversion>
|
||||||
|
<summary>NiFi data flow framework</summary>
|
||||||
|
<description>
|
||||||
|
Nifi is a simple event processing framework largely
|
||||||
|
based on the Flow-Based Programming concepts.
|
||||||
|
</description>
|
||||||
|
<copyright>NONE</copyright>
|
||||||
|
<url>http://nifi.apache.org</url>
|
||||||
|
<group>Utilities</group>
|
||||||
|
<requires>
|
||||||
|
<require>jdk</require>
|
||||||
|
</requires>
|
||||||
|
<prefix>/opt/${project.artifactId}</prefix>
|
||||||
|
<defineStatements>
|
||||||
|
<defineStatement>_use_internal_dependency_generator 0</defineStatement>
|
||||||
|
</defineStatements>
|
||||||
|
<defaultDirmode>750</defaultDirmode>
|
||||||
|
<defaultFilemode>640</defaultFilemode>
|
||||||
|
<defaultUsername>dataflow</defaultUsername>
|
||||||
|
<defaultGroupname>dataflow</defaultGroupname>
|
||||||
|
<mappings>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}</directory>
|
||||||
|
</mapping>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}/bin</directory>
|
||||||
|
<filemode>750</filemode>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/bin/nifi</location>
|
||||||
|
<destination>${project.artifactId}</destination>
|
||||||
|
<filter>true</filter>
|
||||||
|
</source>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/bin/wrapper-linux-x86-32</location>
|
||||||
|
</source>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/bin/wrapper-linux-x86-64</location>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
</mapping>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}/conf</directory>
|
||||||
|
<configuration>true</configuration>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/conf</location>
|
||||||
|
<excludes>
|
||||||
|
<exclude>nifi.properties</exclude>
|
||||||
|
</excludes>
|
||||||
|
<filter>true</filter>
|
||||||
|
</source>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/conf/nifi.properties</location>
|
||||||
|
<destination>${project.artifactId}.properties</destination>
|
||||||
|
<filter>true</filter>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
</mapping>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}/lib</directory>
|
||||||
|
<dependency />
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/lib</location>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*-aix*</exclude>
|
||||||
|
<exclude>**/*-freebsd*</exclude>
|
||||||
|
<exclude>**/*-hpux*</exclude>
|
||||||
|
<exclude>**/*-linux-ia*</exclude>
|
||||||
|
<exclude>**/*-linux-ppc*</exclude>
|
||||||
|
<exclude>**/*-macosx*</exclude>
|
||||||
|
<exclude>**/*-solaris*</exclude>
|
||||||
|
<exclude>**/*-windows*</exclude>
|
||||||
|
</excludes>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
</mapping>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}/docs</directory>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/docs</location>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
</mapping>
|
||||||
|
<mapping>
|
||||||
|
<directory>/opt/${project.artifactId}/${project.artifactId}-${project.version}/logs</directory>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
<location>${project.build.directory}/generated-resources/logs</location>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
</mapping>
|
||||||
|
</mappings>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<assembly>
|
||||||
|
<id>bin</id>
|
||||||
|
<formats>
|
||||||
|
<format>dir</format>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>true</includeBaseDirectory>
|
||||||
|
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
||||||
|
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/generated-resources/bin</directory>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
<directoryMode>0750</directoryMode>
|
||||||
|
<fileMode>0750</fileMode>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/generated-resources/conf</directory>
|
||||||
|
<outputDirectory>conf</outputDirectory>
|
||||||
|
<excludes>
|
||||||
|
<exclude>nifi.properties</exclude>
|
||||||
|
</excludes>
|
||||||
|
<directoryMode>0750</directoryMode>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/generated-resources/lib</directory>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<directoryMode>0750</directoryMode>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/generated-resources/logs</directory>
|
||||||
|
<outputDirectory>logs</outputDirectory>
|
||||||
|
<directoryMode>0750</directoryMode>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.build.directory}/generated-resources/docs</directory>
|
||||||
|
<outputDirectory>docs</outputDirectory>
|
||||||
|
<directoryMode>0750</directoryMode>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/conf/nifi.properties</source>
|
||||||
|
<outputDirectory>conf</outputDirectory>
|
||||||
|
<destName>${project.artifactId}.properties</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/bin/nifi.sh</source>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
<destName>nifi.sh</destName>
|
||||||
|
<fileMode>0750</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/docs/README.md</source>
|
||||||
|
<outputDirectory>docs</outputDirectory>
|
||||||
|
<destName>README.md</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/DISCLAIMER</source>
|
||||||
|
<outputDirectory>./</outputDirectory>
|
||||||
|
<destName>DISCLAIMER</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/DISCLAIMER</source>
|
||||||
|
<outputDirectory>./</outputDirectory>
|
||||||
|
<destName>DISCLAIMER</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/LICENSE</source>
|
||||||
|
<outputDirectory>./</outputDirectory>
|
||||||
|
<destName>LICENSE</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<source>${project.build.directory}/generated-resources/NOTICE</source>
|
||||||
|
<outputDirectory>./</outputDirectory>
|
||||||
|
<destName>NOTICE</destName>
|
||||||
|
<fileMode>0640</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<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">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nifi-core-flowfile-attributes</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>NiFi: Core FlowFile Attributes</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.flowfile.attributes;
|
||||||
|
|
||||||
|
public enum CoreAttributes implements FlowFileAttributeKey {
|
||||||
|
/**
|
||||||
|
* The flowfile's path indicates the relative directory to which a FlowFile belongs and does not
|
||||||
|
* contain the filename
|
||||||
|
*/
|
||||||
|
PATH("path"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flowfile's absolute path indicates the absolute directory to which a FlowFile belongs and does not
|
||||||
|
* contain the filename
|
||||||
|
*/
|
||||||
|
ABSOLUTE_PATH("absolute.path"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filename of the FlowFile. The filename should not contain any directory structure.
|
||||||
|
*/
|
||||||
|
FILENAME("filename"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unique UUID assigned to this FlowFile
|
||||||
|
*/
|
||||||
|
UUID("uuid"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A numeric value indicating the FlowFile priority
|
||||||
|
*/
|
||||||
|
PRIORITY("priority"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MIME Type of this FlowFile
|
||||||
|
*/
|
||||||
|
MIME_TYPE("mime.type"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the reason that a FlowFile is being discarded
|
||||||
|
*/
|
||||||
|
DISCARD_REASON("discard.reason"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates an identifier other than the FlowFile's UUID that is known to refer to this FlowFile.
|
||||||
|
*/
|
||||||
|
ALTERNATE_IDENTIFIER("alternate.identifier");
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private CoreAttributes(final String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String key() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.flowfile.attributes;
|
||||||
|
|
||||||
|
public interface FlowFileAttributeKey {
|
||||||
|
String key();
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/target
|
|
@ -0,0 +1,42 @@
|
||||||
|
<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">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>data-provenance-utils</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>data-provenance-utils</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-api</artifactId>
|
||||||
|
<version>[0.0.1-SNAPSHOT,1.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-core-flowfile-attributes</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
|
||||||
|
import org.apache.nifi.provenance.lineage.LineageComputationType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AsyncLineageSubmission implements ComputeLineageSubmission {
|
||||||
|
private final String lineageIdentifier = UUID.randomUUID().toString();
|
||||||
|
private final Date submissionTime = new Date();
|
||||||
|
|
||||||
|
private final LineageComputationType computationType;
|
||||||
|
private final Long eventId;
|
||||||
|
private final Collection<String> lineageFlowFileUuids;
|
||||||
|
|
||||||
|
private volatile boolean canceled = false;
|
||||||
|
|
||||||
|
private final StandardLineageResult result;
|
||||||
|
|
||||||
|
public AsyncLineageSubmission(final LineageComputationType computationType, final Long eventId, final Collection<String> lineageFlowFileUuids, final int numSteps) {
|
||||||
|
this.computationType = computationType;
|
||||||
|
this.eventId = eventId;
|
||||||
|
this.lineageFlowFileUuids = lineageFlowFileUuids;
|
||||||
|
this.result = new StandardLineageResult(numSteps, lineageFlowFileUuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardLineageResult getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getSubmissionTime() {
|
||||||
|
return submissionTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLineageIdentifier() {
|
||||||
|
return lineageIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
this.canceled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCanceled() {
|
||||||
|
return canceled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LineageComputationType getLineageComputationType() {
|
||||||
|
return computationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getExpandedEventId() {
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getLineageFlowFileUuids() {
|
||||||
|
return lineageFlowFileUuids;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.search.Query;
|
||||||
|
import org.apache.nifi.provenance.search.QuerySubmission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AsyncQuerySubmission implements QuerySubmission {
|
||||||
|
|
||||||
|
public static final int TTL = (int) TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
private final Date submissionTime = new Date();
|
||||||
|
private final Query query;
|
||||||
|
|
||||||
|
private volatile boolean canceled = false;
|
||||||
|
private final StandardQueryResult queryResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an AsyncQuerySubmission with the given query and the given
|
||||||
|
* number of steps, indicating how many results must be added to this
|
||||||
|
* AsyncQuerySubmission before it is considered finished
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
* @param numSteps
|
||||||
|
*/
|
||||||
|
public AsyncQuerySubmission(final Query query, final int numSteps) {
|
||||||
|
this.query = query;
|
||||||
|
queryResult = new StandardQueryResult(query, numSteps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getSubmissionTime() {
|
||||||
|
return submissionTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getQueryIdentifier() {
|
||||||
|
return query.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
this.canceled = true;
|
||||||
|
queryResult.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCanceled() {
|
||||||
|
return canceled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Query getQuery() {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardQueryResult getResult() {
|
||||||
|
return queryResult;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.provenance;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.search.SearchableField;
|
||||||
|
import org.apache.nifi.provenance.search.SearchableFieldType;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class NamedSearchableField implements SearchableField {
|
||||||
|
|
||||||
|
private final String identifier;
|
||||||
|
private final String searchableName;
|
||||||
|
private final SearchableFieldType fieldType;
|
||||||
|
private final String friendlyName;
|
||||||
|
private final boolean attribute;
|
||||||
|
|
||||||
|
NamedSearchableField(final String identifier, final String searchableName, final String friendlyName, final boolean attribute) {
|
||||||
|
this(identifier, searchableName, friendlyName, attribute, SearchableFieldType.STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedSearchableField(final String identifier, final String searchableName, final String friendlyName, final boolean attribute, final SearchableFieldType fieldType) {
|
||||||
|
this.identifier = requireNonNull(identifier);
|
||||||
|
this.searchableName = requireNonNull(searchableName);
|
||||||
|
this.friendlyName = requireNonNull(friendlyName);
|
||||||
|
this.attribute = requireNonNull(attribute);
|
||||||
|
this.fieldType = requireNonNull(fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSearchableFieldName() {
|
||||||
|
return searchableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFriendlyName() {
|
||||||
|
return friendlyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAttribute() {
|
||||||
|
return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchableFieldType getFieldType() {
|
||||||
|
return fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return friendlyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 298347 + searchableName.hashCode() + (attribute ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof SearchableField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SearchableField other = (SearchableField) obj;
|
||||||
|
return (this.searchableName.equals(other.getSearchableFieldName()) && attribute == other.isAttribute());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.search.SearchableField;
|
||||||
|
|
||||||
|
public class SearchableFieldParser {
|
||||||
|
|
||||||
|
public static List<SearchableField> extractSearchableFields(final String indexedFieldString, final boolean predefinedField) {
|
||||||
|
final List<SearchableField> searchableFields = new ArrayList<>();
|
||||||
|
if (indexedFieldString != null) {
|
||||||
|
final String[] split = indexedFieldString.split(",");
|
||||||
|
for (String fieldName : split) {
|
||||||
|
fieldName = fieldName.trim();
|
||||||
|
if (fieldName.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SearchableField searchableField;
|
||||||
|
if (predefinedField) {
|
||||||
|
searchableField = SearchableFields.getSearchableField(fieldName);
|
||||||
|
} else {
|
||||||
|
searchableField = SearchableFields.newSearchableAttribute(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchableField == null) {
|
||||||
|
throw new RuntimeException("Invalid Configuration: Provenance Repository configured to Index field '" + fieldName + "', but this is not a valid field");
|
||||||
|
}
|
||||||
|
searchableFields.add(searchableField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchableFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.search.SearchableField;
|
||||||
|
import org.apache.nifi.provenance.search.SearchableFieldType;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SearchableFields {
|
||||||
|
|
||||||
|
public static final SearchableField Identifier = new NamedSearchableField("Identifier", "identifier", "Identifier", false);
|
||||||
|
public static final SearchableField EventTime = new NamedSearchableField("EventTime", "time", "Event Time", false, SearchableFieldType.DATE);
|
||||||
|
public static final SearchableField FlowFileUUID = new NamedSearchableField("FlowFileUUID", "uuid", "FlowFile UUID", false);
|
||||||
|
public static final SearchableField Filename = new NamedSearchableField("Filename", "filename", "Filename", false);
|
||||||
|
public static final SearchableField EventType = new NamedSearchableField("EventType", "eventType", "Event Type", false);
|
||||||
|
public static final SearchableField TransitURI = new NamedSearchableField("TransitURI", "transitUri", "Transit URI", false);
|
||||||
|
public static final SearchableField ComponentID = new NamedSearchableField("ProcessorID", "processorId", "Component ID", false);
|
||||||
|
public static final SearchableField AlternateIdentifierURI = new NamedSearchableField("AlternateIdentifierURI", "alternateIdentifierUri", "Alternate Identifier URI", false);
|
||||||
|
public static final SearchableField FileSize = new NamedSearchableField("FileSize", "fileSize", "File Size", false, SearchableFieldType.DATA_SIZE);
|
||||||
|
public static final SearchableField Details = new NamedSearchableField("Details", "details", "Details", false, SearchableFieldType.STRING);
|
||||||
|
public static final SearchableField Relationship = new NamedSearchableField("Relationship", "relationship", "Relationship", false, SearchableFieldType.STRING);
|
||||||
|
|
||||||
|
public static final SearchableField LineageStartDate = new NamedSearchableField("LineageStartDate", "lineageStartDate", "Lineage Start Date", false, SearchableFieldType.DATE);
|
||||||
|
public static final SearchableField LineageIdentifier = new NamedSearchableField("LineageIdentifiers", "lineageIdentifier", "Lineage Identifier", false, SearchableFieldType.STRING);
|
||||||
|
|
||||||
|
public static final SearchableField ContentClaimSection = new NamedSearchableField("ContentClaimSection", "contentClaimSection", "Content Claim Section", false, SearchableFieldType.STRING);
|
||||||
|
public static final SearchableField ContentClaimContainer = new NamedSearchableField("ContentClaimContainer", "contentClaimContainer", "Content Claim Container", false, SearchableFieldType.STRING);
|
||||||
|
public static final SearchableField ContentClaimIdentifier = new NamedSearchableField("ContentClaimIdentifier", "contentClaimIdentifier", "Content Claim Identifier", false, SearchableFieldType.STRING);
|
||||||
|
public static final SearchableField ContentClaimOffset = new NamedSearchableField("ContentClaimOffset", "contentClaimOffset", "Content Claim Offset", false, SearchableFieldType.LONG);
|
||||||
|
public static final SearchableField SourceQueueIdentifier = new NamedSearchableField("SourceQueueIdentifier", "sourceQueueIdentifier", "Source Queue Identifier", false, SearchableFieldType.STRING);
|
||||||
|
|
||||||
|
private static final Map<String, SearchableField> standardFields;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final SearchableField[] searchableFields = new SearchableField[]{
|
||||||
|
EventTime, FlowFileUUID, Filename, EventType, TransitURI,
|
||||||
|
ComponentID, AlternateIdentifierURI, FileSize, Relationship, Details,
|
||||||
|
LineageStartDate, LineageIdentifier, ContentClaimSection, ContentClaimContainer, ContentClaimIdentifier,
|
||||||
|
ContentClaimOffset, SourceQueueIdentifier};
|
||||||
|
|
||||||
|
final Map<String, SearchableField> fields = new HashMap<>();
|
||||||
|
for (final SearchableField field : searchableFields) {
|
||||||
|
fields.put(field.getIdentifier(), field);
|
||||||
|
}
|
||||||
|
|
||||||
|
standardFields = Collections.unmodifiableMap(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchableFields() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<SearchableField> getStandardFields() {
|
||||||
|
return standardFields.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SearchableField getSearchableField(final String fieldIdentifier) {
|
||||||
|
return standardFields.get(fieldIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SearchableField newSearchableAttribute(final String attributeName) {
|
||||||
|
return new NamedSearchableField(attributeName, attributeName, attributeName, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,324 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
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 java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.lineage.ComputeLineageResult;
|
||||||
|
import org.apache.nifi.provenance.lineage.EdgeNode;
|
||||||
|
import org.apache.nifi.provenance.lineage.EventNode;
|
||||||
|
import org.apache.nifi.provenance.lineage.FlowFileNode;
|
||||||
|
import org.apache.nifi.provenance.lineage.LineageEdge;
|
||||||
|
import org.apache.nifi.provenance.lineage.LineageNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class StandardLineageResult implements ComputeLineageResult {
|
||||||
|
|
||||||
|
public static final int TTL = (int) TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES);
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(StandardLineageResult.class);
|
||||||
|
|
||||||
|
private final Collection<String> flowFileUuids;
|
||||||
|
private final Collection<ProvenanceEventRecord> relevantRecords = new ArrayList<>();
|
||||||
|
private final Set<LineageNode> nodes = new HashSet<>();
|
||||||
|
private final Set<LineageEdge> edges = new HashSet<>();
|
||||||
|
private final int numSteps;
|
||||||
|
private final long creationNanos;
|
||||||
|
private long computationNanos;
|
||||||
|
|
||||||
|
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||||
|
private final Lock readLock = rwLock.readLock();
|
||||||
|
private final Lock writeLock = rwLock.writeLock();
|
||||||
|
|
||||||
|
private Date expirationDate = null;
|
||||||
|
private String error = null;
|
||||||
|
private int numCompletedSteps = 0;
|
||||||
|
|
||||||
|
private volatile boolean canceled = false;
|
||||||
|
|
||||||
|
public StandardLineageResult(final int numSteps, final Collection<String> flowFileUuids) {
|
||||||
|
this.numSteps = numSteps;
|
||||||
|
this.creationNanos = System.nanoTime();
|
||||||
|
this.flowFileUuids = flowFileUuids;
|
||||||
|
|
||||||
|
updateExpiration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LineageNode> getNodes() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return new ArrayList<>(nodes);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LineageEdge> getEdges() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return new ArrayList<>(edges);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfEdges() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return edges.size();
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfNodes() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return nodes.size();
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getComputationTime(final TimeUnit timeUnit) {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return timeUnit.convert(computationNanos, TimeUnit.NANOSECONDS);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getExpiration() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return expirationDate;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getError() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return error;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPercentComplete() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return (numSteps < 1) ? 100 : (int) (((float) numCompletedSteps / (float) numSteps) * 100.0F);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return numCompletedSteps >= numSteps || canceled;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(final String error) {
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
|
this.error = error;
|
||||||
|
numCompletedSteps++;
|
||||||
|
|
||||||
|
updateExpiration();
|
||||||
|
|
||||||
|
if (numCompletedSteps >= numSteps) {
|
||||||
|
computationNanos = System.nanoTime() - creationNanos;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(final Collection<ProvenanceEventRecord> records) {
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
|
relevantRecords.addAll(records);
|
||||||
|
|
||||||
|
numCompletedSteps++;
|
||||||
|
updateExpiration();
|
||||||
|
|
||||||
|
if (numCompletedSteps >= numSteps && error == null) {
|
||||||
|
computeLineage();
|
||||||
|
computationNanos = System.nanoTime() - creationNanos;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the lineage from the relevant Provenance Event Records. This
|
||||||
|
* method must be called with the write lock held and is only going to be
|
||||||
|
* useful after all of the records have been successfully obtained
|
||||||
|
*/
|
||||||
|
private void computeLineage() {
|
||||||
|
final long startNanos = System.nanoTime();
|
||||||
|
|
||||||
|
nodes.clear();
|
||||||
|
edges.clear();
|
||||||
|
|
||||||
|
Map<String, LineageNode> lastEventMap = new HashMap<>(); // maps FlowFile UUID to last event for that FlowFile
|
||||||
|
final List<ProvenanceEventRecord> sortedRecords = new ArrayList<>(relevantRecords);
|
||||||
|
Collections.sort(sortedRecords, new Comparator<ProvenanceEventRecord>() {
|
||||||
|
@Override
|
||||||
|
public int compare(final ProvenanceEventRecord o1, final ProvenanceEventRecord o2) {
|
||||||
|
// Sort on Event Time, then Event ID.
|
||||||
|
final int eventTimeComparison = Long.compare(o1.getEventTime(), o2.getEventTime());
|
||||||
|
if (eventTimeComparison == 0) {
|
||||||
|
return Long.compare(o1.getEventId(), o2.getEventId());
|
||||||
|
} else {
|
||||||
|
return eventTimeComparison;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// convert the StandardProvenanceRecord objects into Lineage nodes (FlowFileNode, EventNodes).
|
||||||
|
for (final ProvenanceEventRecord record : sortedRecords) {
|
||||||
|
final LineageNode lineageNode = new EventNode(record);
|
||||||
|
final boolean added = nodes.add(lineageNode);
|
||||||
|
if (!added) {
|
||||||
|
logger.debug("Did not add {} because it already exists in the 'nodes' set", lineageNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an edge that connects this node to the previous node for the same FlowFile UUID.
|
||||||
|
final LineageNode lastNode = lastEventMap.get(record.getFlowFileUuid());
|
||||||
|
if (lastNode != null) {
|
||||||
|
// We calculate the Edge UUID based on whether or not this event is a SPAWN.
|
||||||
|
// If this event is a SPAWN, then we want to use the previous node's UUID because a
|
||||||
|
// SPAWN Event's UUID is not necessarily what we want, since a SPAWN Event's UUID pertains to
|
||||||
|
// only one of (potentially) many UUIDs associated with the event. Otherwise, we know that
|
||||||
|
// the UUID of this record is appropriate, so we just use it.
|
||||||
|
final String edgeUuid;
|
||||||
|
|
||||||
|
switch (record.getEventType()) {
|
||||||
|
case JOIN:
|
||||||
|
case CLONE:
|
||||||
|
case REPLAY:
|
||||||
|
edgeUuid = lastNode.getFlowFileUuid();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
edgeUuid = record.getFlowFileUuid();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
edges.add(new EdgeNode(edgeUuid, lastNode, lineageNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
lastEventMap.put(record.getFlowFileUuid(), lineageNode);
|
||||||
|
|
||||||
|
switch (record.getEventType()) {
|
||||||
|
case FORK:
|
||||||
|
case JOIN:
|
||||||
|
case REPLAY:
|
||||||
|
case CLONE: {
|
||||||
|
// For events that create FlowFile nodes, we need to create the FlowFile Nodes and associated Edges, as appropriate
|
||||||
|
for (final String childUuid : record.getChildUuids()) {
|
||||||
|
if (flowFileUuids.contains(childUuid)) {
|
||||||
|
final FlowFileNode childNode = new FlowFileNode(childUuid, record.getEventTime());
|
||||||
|
final boolean isNewFlowFile = nodes.add(childNode);
|
||||||
|
if (!isNewFlowFile) {
|
||||||
|
final String msg = "Unable to generate Lineage Graph because multiple events were registered claiming to have generated the same FlowFile (UUID = " + childNode.getFlowFileUuid() + ")";
|
||||||
|
logger.error(msg);
|
||||||
|
setError(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
edges.add(new EdgeNode(childNode.getFlowFileUuid(), lineageNode, childNode));
|
||||||
|
lastEventMap.put(childUuid, childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (final String parentUuid : record.getParentUuids()) {
|
||||||
|
LineageNode lastNodeForParent = lastEventMap.get(parentUuid);
|
||||||
|
if (lastNodeForParent != null && !lastNodeForParent.equals(lineageNode)) {
|
||||||
|
edges.add(new EdgeNode(parentUuid, lastNodeForParent, lineageNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
lastEventMap.put(parentUuid, lineageNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RECEIVE:
|
||||||
|
case CREATE: {
|
||||||
|
// for a receive event, we want to create a FlowFile Node that represents the FlowFile received
|
||||||
|
// and create an edge from the Receive Event to the FlowFile Node
|
||||||
|
final LineageNode flowFileNode = new FlowFileNode(record.getFlowFileUuid(), record.getEventTime());
|
||||||
|
final boolean isNewFlowFile = nodes.add(flowFileNode);
|
||||||
|
if (!isNewFlowFile) {
|
||||||
|
final String msg = "Found cycle in graph. This indicates that multiple events were registered claiming to have generated the same FlowFile (UUID = " + flowFileNode.getFlowFileUuid() + ")";
|
||||||
|
setError(msg);
|
||||||
|
logger.error(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
edges.add(new EdgeNode(record.getFlowFileUuid(), lineageNode, flowFileNode));
|
||||||
|
lastEventMap.put(record.getFlowFileUuid(), flowFileNode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final long nanos = System.nanoTime() - startNanos;
|
||||||
|
logger.debug("Finished building lineage with {} nodes and {} edges in {} millis", nodes.size(), edges.size(), TimeUnit.NANOSECONDS.toMillis(nanos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel() {
|
||||||
|
this.canceled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called with write lock!
|
||||||
|
*/
|
||||||
|
private void updateExpiration() {
|
||||||
|
expirationDate = new Date(System.currentTimeMillis() + TTL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,752 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
||||||
|
import org.apache.nifi.processor.Relationship;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holder for provenance relevant information
|
||||||
|
* <p/>
|
||||||
|
* @author none
|
||||||
|
*/
|
||||||
|
public final class StandardProvenanceEventRecord implements ProvenanceEventRecord {
|
||||||
|
|
||||||
|
private final long eventTime;
|
||||||
|
private final long entryDate;
|
||||||
|
private final ProvenanceEventType eventType;
|
||||||
|
private final long lineageStartDate;
|
||||||
|
private final Set<String> lineageIdentifiers;
|
||||||
|
private final String componentId;
|
||||||
|
private final String componentType;
|
||||||
|
private final String transitUri;
|
||||||
|
private final String sourceSystemFlowFileIdentifier;
|
||||||
|
private final String uuid;
|
||||||
|
private final List<String> parentUuids;
|
||||||
|
private final List<String> childrenUuids;
|
||||||
|
private final String alternateIdentifierUri;
|
||||||
|
private final String details;
|
||||||
|
private final String relationship;
|
||||||
|
private final long storageByteOffset;
|
||||||
|
private final String storageFilename;
|
||||||
|
private final long eventDuration;
|
||||||
|
|
||||||
|
private final String contentClaimSection;
|
||||||
|
private final String contentClaimContainer;
|
||||||
|
private final String contentClaimIdentifier;
|
||||||
|
private final Long contentClaimOffset;
|
||||||
|
private final long contentSize;
|
||||||
|
|
||||||
|
private final String previousClaimSection;
|
||||||
|
private final String previousClaimContainer;
|
||||||
|
private final String previousClaimIdentifier;
|
||||||
|
private final Long previousClaimOffset;
|
||||||
|
private final Long previousSize;
|
||||||
|
|
||||||
|
private final String sourceQueueIdentifier;
|
||||||
|
|
||||||
|
private final Map<String, String> previousAttributes;
|
||||||
|
private final Map<String, String> updatedAttributes;
|
||||||
|
|
||||||
|
private volatile long eventId;
|
||||||
|
|
||||||
|
private StandardProvenanceEventRecord(final Builder builder) {
|
||||||
|
this.eventTime = builder.eventTime;
|
||||||
|
this.entryDate = builder.entryDate;
|
||||||
|
this.eventType = builder.eventType;
|
||||||
|
this.componentId = builder.componentId;
|
||||||
|
this.componentType = builder.componentType;
|
||||||
|
this.transitUri = builder.transitUri;
|
||||||
|
this.sourceSystemFlowFileIdentifier = builder.sourceSystemFlowFileIdentifier;
|
||||||
|
this.uuid = builder.uuid;
|
||||||
|
this.parentUuids = builder.parentUuids;
|
||||||
|
this.childrenUuids = builder.childrenUuids;
|
||||||
|
this.alternateIdentifierUri = builder.alternateIdentifierUri;
|
||||||
|
this.details = builder.details;
|
||||||
|
this.relationship = builder.relationship;
|
||||||
|
this.storageByteOffset = builder.storageByteOffset;
|
||||||
|
this.storageFilename = builder.storageFilename;
|
||||||
|
this.eventDuration = builder.eventDuration;
|
||||||
|
this.lineageStartDate = builder.lineageStartDate;
|
||||||
|
this.lineageIdentifiers = Collections.unmodifiableSet(builder.lineageIdentifiers);
|
||||||
|
|
||||||
|
previousClaimSection = builder.previousClaimSection;
|
||||||
|
previousClaimContainer = builder.previousClaimContainer;
|
||||||
|
previousClaimIdentifier = builder.previousClaimIdentifier;
|
||||||
|
previousClaimOffset = builder.previousClaimOffset;
|
||||||
|
previousSize = builder.previousSize;
|
||||||
|
|
||||||
|
contentClaimSection = builder.contentClaimSection;
|
||||||
|
contentClaimContainer = builder.contentClaimContainer;
|
||||||
|
contentClaimIdentifier = builder.contentClaimIdentifier;
|
||||||
|
contentClaimOffset = builder.contentClaimOffset;
|
||||||
|
contentSize = builder.contentSize;
|
||||||
|
|
||||||
|
previousAttributes = builder.previousAttributes == null ? Collections.<String, String>emptyMap() : Collections.unmodifiableMap(builder.previousAttributes);
|
||||||
|
updatedAttributes = builder.updatedAttributes == null ? Collections.<String, String>emptyMap() : Collections.unmodifiableMap(builder.updatedAttributes);
|
||||||
|
|
||||||
|
sourceQueueIdentifier = builder.sourceQueueIdentifier;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStorageFilename() {
|
||||||
|
return storageFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStorageByteOffset() {
|
||||||
|
return storageByteOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEventId(final long eventId) {
|
||||||
|
this.eventId = eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventId() {
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventTime() {
|
||||||
|
return eventTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getLineageIdentifiers() {
|
||||||
|
return lineageIdentifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLineageStartDate() {
|
||||||
|
return lineageStartDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getFileSize() {
|
||||||
|
return contentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getPreviousFileSize() {
|
||||||
|
return previousSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProvenanceEventType getEventType() {
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
final Map<String, String> allAttrs = new HashMap<>(previousAttributes.size() + updatedAttributes.size());
|
||||||
|
allAttrs.putAll(previousAttributes);
|
||||||
|
for (final Map.Entry<String, String> entry : updatedAttributes.entrySet()) {
|
||||||
|
if (entry.getValue() != null) {
|
||||||
|
allAttrs.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getComponentId() {
|
||||||
|
return componentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getComponentType() {
|
||||||
|
return componentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTransitUri() {
|
||||||
|
return transitUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceSystemFlowFileIdentifier() {
|
||||||
|
return sourceSystemFlowFileIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlowFileUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getParentUuids() {
|
||||||
|
return parentUuids == null ? Collections.<String>emptyList() : parentUuids;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getChildUuids() {
|
||||||
|
return childrenUuids == null ? Collections.<String>emptyList() : childrenUuids;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlternateIdentifierUri() {
|
||||||
|
return alternateIdentifierUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventDuration() {
|
||||||
|
return eventDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDetails() {
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRelationship() {
|
||||||
|
return relationship;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getFlowFileEntryDate() {
|
||||||
|
return entryDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentClaimSection() {
|
||||||
|
return contentClaimSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentClaimContainer() {
|
||||||
|
return contentClaimContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentClaimIdentifier() {
|
||||||
|
return contentClaimIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getContentClaimOffset() {
|
||||||
|
return contentClaimOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceQueueIdentifier() {
|
||||||
|
return sourceQueueIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPreviousAttributes() {
|
||||||
|
return previousAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPreviousContentClaimContainer() {
|
||||||
|
return previousClaimContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPreviousContentClaimIdentifier() {
|
||||||
|
return previousClaimIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getPreviousContentClaimOffset() {
|
||||||
|
return previousClaimOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPreviousContentClaimSection() {
|
||||||
|
return previousClaimSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getUpdatedAttributes() {
|
||||||
|
return updatedAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int eventTypeCode;
|
||||||
|
if (eventType == ProvenanceEventType.CLONE || eventType == ProvenanceEventType.JOIN || eventType == ProvenanceEventType.FORK) {
|
||||||
|
eventTypeCode = 1472;
|
||||||
|
} else if (eventType == ProvenanceEventType.REPLAY) {
|
||||||
|
eventTypeCode = 21479 + (int) (0x7FFFFFFF & eventTime); // use lower bits of event time.
|
||||||
|
} else {
|
||||||
|
eventTypeCode = 4812 + eventType.hashCode() + 4 * uuid.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -37423 + 3 * componentId.hashCode() + (transitUri == null ? 0 : 41 * transitUri.hashCode())
|
||||||
|
+ (relationship == null ? 0 : 47 * relationship.hashCode()) + 44 * eventTypeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof StandardProvenanceEventRecord)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final StandardProvenanceEventRecord other = (StandardProvenanceEventRecord) obj;
|
||||||
|
// If event ID's are populated and not equal, return false. If they have not yet been populated, do not
|
||||||
|
// use them in the comparison.
|
||||||
|
if (eventId > 0L && other.getEventId() > 0L && eventId != other.getEventId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (eventType != other.eventType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!componentId.equals(other.componentId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (different(parentUuids, other.parentUuids)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (different(childrenUuids, other.childrenUuids)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPAWN had issues indicating which should be the event's FlowFileUUID in the case that there is 1 parent and 1 child.
|
||||||
|
if (!uuid.equals(other.uuid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (different(transitUri, other.transitUri)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (different(relationship, other.relationship)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(eventType == ProvenanceEventType.REPLAY && eventTime != other.getEventTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean different(final Object a, final Object b) {
|
||||||
|
if (a == null && b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean different(final List<String> a, final List<String> b) {
|
||||||
|
if (a == null && b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == null && b != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a != null && b == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.size() != b.size()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> sortedA = new ArrayList<>(a);
|
||||||
|
final List<String> sortedB = new ArrayList<>(b);
|
||||||
|
|
||||||
|
Collections.sort(sortedA);
|
||||||
|
Collections.sort(sortedB);
|
||||||
|
|
||||||
|
for (int i = 0; i < sortedA.size(); i++) {
|
||||||
|
if (!sortedA.get(i).equals(sortedB.get(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ProvenanceEventRecord ["
|
||||||
|
+ "eventId=" + eventId
|
||||||
|
+ ", eventType=" + eventType
|
||||||
|
+ ", eventTime=" + new Date(eventTime)
|
||||||
|
+ ", uuid=" + uuid
|
||||||
|
+ ", fileSize=" + contentSize
|
||||||
|
+ ", componentId=" + componentId
|
||||||
|
+ ", transitUri=" + transitUri
|
||||||
|
+ ", sourceSystemFlowFileIdentifier=" + sourceSystemFlowFileIdentifier
|
||||||
|
+ ", parentUuids=" + parentUuids
|
||||||
|
+ ", alternateIdentifierUri=" + alternateIdentifierUri + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder implements ProvenanceEventBuilder {
|
||||||
|
|
||||||
|
private long eventTime = System.currentTimeMillis();
|
||||||
|
private long entryDate;
|
||||||
|
private long lineageStartDate;
|
||||||
|
private Set<String> lineageIdentifiers = new HashSet<>();
|
||||||
|
private ProvenanceEventType eventType = null;
|
||||||
|
private String componentId = null;
|
||||||
|
private String componentType = null;
|
||||||
|
private String sourceSystemFlowFileIdentifier = null;
|
||||||
|
private String transitUri = null;
|
||||||
|
private String uuid = null;
|
||||||
|
private List<String> parentUuids = null;
|
||||||
|
private List<String> childrenUuids = null;
|
||||||
|
private String contentType = null;
|
||||||
|
private String alternateIdentifierUri = null;
|
||||||
|
private String details = null;
|
||||||
|
private String relationship = null;
|
||||||
|
private long storageByteOffset = -1L;
|
||||||
|
private long eventDuration = -1L;
|
||||||
|
private String storageFilename;
|
||||||
|
|
||||||
|
private String contentClaimSection;
|
||||||
|
private String contentClaimContainer;
|
||||||
|
private String contentClaimIdentifier;
|
||||||
|
private Long contentClaimOffset;
|
||||||
|
private Long contentSize;
|
||||||
|
|
||||||
|
private String previousClaimSection;
|
||||||
|
private String previousClaimContainer;
|
||||||
|
private String previousClaimIdentifier;
|
||||||
|
private Long previousClaimOffset;
|
||||||
|
private Long previousSize;
|
||||||
|
|
||||||
|
private String sourceQueueIdentifier;
|
||||||
|
|
||||||
|
private Map<String, String> previousAttributes;
|
||||||
|
private Map<String, String> updatedAttributes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder fromEvent(final ProvenanceEventRecord event) {
|
||||||
|
eventTime = event.getEventTime();
|
||||||
|
entryDate = event.getFlowFileEntryDate();
|
||||||
|
lineageStartDate = event.getLineageStartDate();
|
||||||
|
lineageIdentifiers = event.getLineageIdentifiers();
|
||||||
|
eventType = event.getEventType();
|
||||||
|
componentId = event.getComponentId();
|
||||||
|
componentType = event.getComponentType();
|
||||||
|
transitUri = event.getTransitUri();
|
||||||
|
sourceSystemFlowFileIdentifier = event.getSourceSystemFlowFileIdentifier();
|
||||||
|
uuid = event.getFlowFileUuid();
|
||||||
|
parentUuids = event.getParentUuids();
|
||||||
|
childrenUuids = event.getChildUuids();
|
||||||
|
alternateIdentifierUri = event.getAlternateIdentifierUri();
|
||||||
|
eventDuration = event.getEventDuration();
|
||||||
|
previousAttributes = event.getPreviousAttributes();
|
||||||
|
updatedAttributes = event.getUpdatedAttributes();
|
||||||
|
details = event.getDetails();
|
||||||
|
relationship = event.getRelationship();
|
||||||
|
|
||||||
|
contentClaimSection = event.getContentClaimSection();
|
||||||
|
contentClaimContainer = event.getContentClaimContainer();
|
||||||
|
contentClaimIdentifier = event.getContentClaimIdentifier();
|
||||||
|
contentClaimOffset = event.getContentClaimOffset();
|
||||||
|
contentSize = event.getFileSize();
|
||||||
|
|
||||||
|
previousClaimSection = event.getPreviousContentClaimSection();
|
||||||
|
previousClaimContainer = event.getPreviousContentClaimContainer();
|
||||||
|
previousClaimIdentifier = event.getPreviousContentClaimIdentifier();
|
||||||
|
previousClaimOffset = event.getPreviousContentClaimOffset();
|
||||||
|
previousSize = event.getPreviousFileSize();
|
||||||
|
|
||||||
|
sourceQueueIdentifier = event.getSourceQueueIdentifier();
|
||||||
|
|
||||||
|
if (event instanceof StandardProvenanceEventRecord) {
|
||||||
|
final StandardProvenanceEventRecord standardProvEvent = (StandardProvenanceEventRecord) event;
|
||||||
|
storageByteOffset = standardProvEvent.storageByteOffset;
|
||||||
|
storageFilename = standardProvEvent.storageFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setFlowFileEntryDate(final long entryDate) {
|
||||||
|
this.entryDate = entryDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setLineageIdentifiers(final Set<String> lineageIdentifiers) {
|
||||||
|
this.lineageIdentifiers = lineageIdentifiers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setAttributes(final Map<String, String> previousAttributes, final Map<String, String> updatedAttributes) {
|
||||||
|
this.previousAttributes = previousAttributes;
|
||||||
|
this.updatedAttributes = updatedAttributes;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setFlowFileUUID(final String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setStorageLocation(final String filename, final long offset) {
|
||||||
|
this.storageFilename = filename;
|
||||||
|
this.storageByteOffset = offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setEventTime(long eventTime) {
|
||||||
|
this.eventTime = eventTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setEventDuration(final long millis) {
|
||||||
|
this.eventDuration = millis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setLineageStartDate(final long startDate) {
|
||||||
|
this.lineageStartDate = startDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addLineageIdentifier(final String lineageIdentifier) {
|
||||||
|
this.lineageIdentifiers.add(lineageIdentifier);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setEventType(ProvenanceEventType eventType) {
|
||||||
|
this.eventType = eventType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setComponentId(String componentId) {
|
||||||
|
this.componentId = componentId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setComponentType(String componentType) {
|
||||||
|
this.componentType = componentType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setSourceSystemFlowFileIdentifier(String sourceSystemFlowFileIdentifier) {
|
||||||
|
this.sourceSystemFlowFileIdentifier = sourceSystemFlowFileIdentifier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setTransitUri(String transitUri) {
|
||||||
|
this.transitUri = transitUri;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder addParentFlowFile(final FlowFile parentFlowFile) {
|
||||||
|
if (this.parentUuids == null) {
|
||||||
|
this.parentUuids = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.parentUuids.add(parentFlowFile.getAttribute(CoreAttributes.UUID.key()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addParentUuid(final String uuid) {
|
||||||
|
if (this.parentUuids == null) {
|
||||||
|
this.parentUuids = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.parentUuids.add(uuid);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder removeParentFlowFile(final FlowFile parentFlowFile) {
|
||||||
|
if (this.parentUuids == null) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
parentUuids.remove(parentFlowFile.getAttribute(CoreAttributes.UUID.key()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder addChildFlowFile(final FlowFile childFlowFile) {
|
||||||
|
if (this.childrenUuids == null) {
|
||||||
|
this.childrenUuids = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.childrenUuids.add(childFlowFile.getAttribute(CoreAttributes.UUID.key()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addChildUuid(final String uuid) {
|
||||||
|
if (this.childrenUuids == null) {
|
||||||
|
this.childrenUuids = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.childrenUuids.add(uuid);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder removeChildFlowFile(final FlowFile childFlowFile) {
|
||||||
|
if (this.childrenUuids == null) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
childrenUuids.remove(childFlowFile.getAttribute(CoreAttributes.UUID.key()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setContentType(String contentType) {
|
||||||
|
this.contentType = contentType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setAlternateIdentifierUri(String alternateIdentifierUri) {
|
||||||
|
this.alternateIdentifierUri = alternateIdentifierUri;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setDetails(String details) {
|
||||||
|
this.details = details;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setRelationship(Relationship relationship) {
|
||||||
|
this.relationship = relationship.getName();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setRelationship(final String relationship) {
|
||||||
|
this.relationship = relationship;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProvenanceEventBuilder fromFlowFile(final FlowFile flowFile) {
|
||||||
|
setFlowFileEntryDate(flowFile.getEntryDate());
|
||||||
|
setLineageIdentifiers(flowFile.getLineageIdentifiers());
|
||||||
|
setLineageStartDate(flowFile.getLineageStartDate());
|
||||||
|
setAttributes(Collections.<String, String>emptyMap(), flowFile.getAttributes());
|
||||||
|
uuid = flowFile.getAttribute(CoreAttributes.UUID.key());
|
||||||
|
this.contentSize = flowFile.getSize();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setPreviousContentClaim(final String container, final String section, final String identifier, final Long offset, final long size) {
|
||||||
|
previousClaimSection = section;
|
||||||
|
previousClaimContainer = container;
|
||||||
|
previousClaimIdentifier = identifier;
|
||||||
|
previousClaimOffset = offset;
|
||||||
|
previousSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setCurrentContentClaim(final String container, final String section, final String identifier, final Long offset, final long size) {
|
||||||
|
contentClaimSection = section;
|
||||||
|
contentClaimContainer = container;
|
||||||
|
contentClaimIdentifier = identifier;
|
||||||
|
contentClaimOffset = offset;
|
||||||
|
contentSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder setSourceQueueIdentifier(final String identifier) {
|
||||||
|
sourceQueueIdentifier = identifier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSet(final Object value, final String name) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new IllegalStateException("Cannot create Provenance Event Record because " + name + " is not set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProvenanceEventType getEventType() {
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getChildUuids() {
|
||||||
|
return Collections.unmodifiableList(childrenUuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getParentUuids() {
|
||||||
|
return Collections.unmodifiableList(parentUuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardProvenanceEventRecord build() {
|
||||||
|
assertSet(eventType, "Event Type");
|
||||||
|
assertSet(componentId, "Component ID");
|
||||||
|
assertSet(componentType, "Component Type");
|
||||||
|
assertSet(uuid, "FlowFile UUID");
|
||||||
|
assertSet(contentSize, "FlowFile Size");
|
||||||
|
|
||||||
|
switch (eventType) {
|
||||||
|
case ADDINFO:
|
||||||
|
if (alternateIdentifierUri == null) {
|
||||||
|
throw new IllegalStateException("Cannot create Provenance Event Record of type " + eventType + " because no alternate identifiers have been set");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RECEIVE:
|
||||||
|
case SEND:
|
||||||
|
assertSet(transitUri, "Transit URI");
|
||||||
|
break;
|
||||||
|
case ROUTE:
|
||||||
|
assertSet(relationship, "Relationship");
|
||||||
|
break;
|
||||||
|
case CLONE:
|
||||||
|
case FORK:
|
||||||
|
case JOIN:
|
||||||
|
if ((parentUuids == null || parentUuids.isEmpty()) && (childrenUuids == null || childrenUuids.isEmpty())) {
|
||||||
|
throw new IllegalStateException("Cannot create Provenance Event Record of type " + eventType + " because no Parent UUIDs or Children UUIDs have been set");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StandardProvenanceEventRecord(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
import org.apache.nifi.provenance.search.Query;
|
||||||
|
import org.apache.nifi.provenance.search.QueryResult;
|
||||||
|
|
||||||
|
public class StandardQueryResult implements QueryResult {
|
||||||
|
|
||||||
|
public static final int TTL = (int) TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES);
|
||||||
|
private final Query query;
|
||||||
|
private final long creationNanos;
|
||||||
|
|
||||||
|
private final int numSteps;
|
||||||
|
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||||
|
private final Lock readLock = rwLock.readLock();
|
||||||
|
|
||||||
|
private final Lock writeLock = rwLock.writeLock();
|
||||||
|
// guarded by writeLock
|
||||||
|
private final List<ProvenanceEventRecord> matchingRecords = new ArrayList<>();
|
||||||
|
private long totalHitCount;
|
||||||
|
private int numCompletedSteps = 0;
|
||||||
|
private Date expirationDate;
|
||||||
|
private String error;
|
||||||
|
private long queryTime;
|
||||||
|
|
||||||
|
private volatile boolean canceled = false;
|
||||||
|
|
||||||
|
public StandardQueryResult(final Query query, final int numSteps) {
|
||||||
|
this.query = query;
|
||||||
|
this.numSteps = numSteps;
|
||||||
|
this.creationNanos = System.nanoTime();
|
||||||
|
|
||||||
|
updateExpiration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProvenanceEventRecord> getMatchingEvents() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
if (matchingRecords.size() <= query.getMaxResults()) {
|
||||||
|
return new ArrayList<>(matchingRecords);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<ProvenanceEventRecord> copy = new ArrayList<>(query.getMaxResults());
|
||||||
|
for (int i = 0; i < query.getMaxResults(); i++) {
|
||||||
|
copy.add(matchingRecords.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTotalHitCount() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return totalHitCount;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getQueryTime() {
|
||||||
|
return queryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getExpiration() {
|
||||||
|
return expirationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPercentComplete() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return (numSteps < 1) ? 100 : (int) (((float) numCompletedSteps / (float) numSteps) * 100.0F);
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
readLock.lock();
|
||||||
|
try {
|
||||||
|
return numCompletedSteps >= numSteps || canceled;
|
||||||
|
} finally {
|
||||||
|
readLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel() {
|
||||||
|
this.canceled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(final String error) {
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
|
this.error = error;
|
||||||
|
numCompletedSteps++;
|
||||||
|
|
||||||
|
updateExpiration();
|
||||||
|
if (numCompletedSteps >= numSteps) {
|
||||||
|
final long searchNanos = System.nanoTime() - creationNanos;
|
||||||
|
queryTime = TimeUnit.MILLISECONDS.convert(searchNanos, TimeUnit.NANOSECONDS);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(final Collection<ProvenanceEventRecord> matchingRecords, final long totalHits) {
|
||||||
|
writeLock.lock();
|
||||||
|
try {
|
||||||
|
this.matchingRecords.addAll(matchingRecords);
|
||||||
|
this.totalHitCount += totalHits;
|
||||||
|
|
||||||
|
numCompletedSteps++;
|
||||||
|
updateExpiration();
|
||||||
|
|
||||||
|
if (numCompletedSteps >= numSteps) {
|
||||||
|
final long searchNanos = System.nanoTime() - creationNanos;
|
||||||
|
queryTime = TimeUnit.MILLISECONDS.convert(searchNanos, TimeUnit.NANOSECONDS);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
writeLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called with write lock!
|
||||||
|
*/
|
||||||
|
private void updateExpiration() {
|
||||||
|
expirationDate = new Date(System.currentTimeMillis() + TTL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance.lineage;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class EdgeNode implements LineageEdge {
|
||||||
|
|
||||||
|
private final String uuid;
|
||||||
|
private final LineageNode source;
|
||||||
|
private final LineageNode destination;
|
||||||
|
|
||||||
|
public EdgeNode(final String uuid, final LineageNode source, final LineageNode destination) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.source = requireNonNull(source);
|
||||||
|
this.destination = requireNonNull(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LineageNode getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LineageNode getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 43298293 + source.hashCode() + destination.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof EdgeNode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EdgeNode other = (EdgeNode) obj;
|
||||||
|
return (source.equals(other.source) && destination.equals(other.destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Edge[Source=" + source + ", Destination=" + destination + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance.lineage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.nifi.flowfile.attributes.CoreAttributes;
|
||||||
|
import org.apache.nifi.provenance.ProvenanceEventRecord;
|
||||||
|
import org.apache.nifi.provenance.ProvenanceEventType;
|
||||||
|
|
||||||
|
public class EventNode implements ProvenanceEventLineageNode {
|
||||||
|
|
||||||
|
private final ProvenanceEventRecord record;
|
||||||
|
private String clusterNodeIdentifier = null;
|
||||||
|
|
||||||
|
public EventNode(final ProvenanceEventRecord event) {
|
||||||
|
this.record = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return String.valueOf(getEventIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClusterNodeIdentifier() {
|
||||||
|
return clusterNodeIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClusterNodeIdentifier(final String nodeIdentifier) {
|
||||||
|
this.clusterNodeIdentifier = nodeIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LineageNodeType getNodeType() {
|
||||||
|
return LineageNodeType.PROVENANCE_EVENT_NODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProvenanceEventType getEventType() {
|
||||||
|
return record.getEventType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimestamp() {
|
||||||
|
return record.getEventTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getEventIdentifier() {
|
||||||
|
return record.getEventId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlowFileUuid() {
|
||||||
|
return record.getAttributes().get(CoreAttributes.UUID.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getParentUuids() {
|
||||||
|
return record.getParentUuids();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getChildUuids() {
|
||||||
|
return record.getChildUuids();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 2938472 + record.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof EventNode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EventNode other = (EventNode) obj;
|
||||||
|
return record.equals(other.record);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Event[ID=" + record.getEventId() + ", Type=" + record.getEventType() + ", UUID=" + record.getFlowFileUuid() + ", Component=" + record.getComponentId() + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.provenance.lineage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class FlowFileLineage implements Lineage {
|
||||||
|
|
||||||
|
private final List<LineageNode> nodes;
|
||||||
|
private final List<LineageEdge> edges;
|
||||||
|
|
||||||
|
public FlowFileLineage(final Collection<LineageNode> nodes, final Collection<LineageEdge> edges) {
|
||||||
|
this.nodes = new ArrayList<>(requireNonNull(nodes));
|
||||||
|
this.edges = new ArrayList<>(requireNonNull(edges));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LineageNode> getNodes() {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LineageEdge> getEdges() {
|
||||||
|
return edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int sum = 923;
|
||||||
|
for (final LineageNode node : nodes) {
|
||||||
|
sum += node.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final LineageEdge edge : edges) {
|
||||||
|
sum += edge.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof FlowFileLineage)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FlowFileLineage other = (FlowFileLineage) obj;
|
||||||
|
return nodes.equals(other.nodes) && edges.equals(other.edges);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.provenance.lineage;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class FlowFileNode implements LineageNode {
|
||||||
|
|
||||||
|
private final String flowFileUuid;
|
||||||
|
private final long creationTime;
|
||||||
|
private String clusterNodeIdentifier;
|
||||||
|
|
||||||
|
public FlowFileNode(final String flowFileUuid, final long flowFileCreationTime) {
|
||||||
|
this.flowFileUuid = requireNonNull(flowFileUuid);
|
||||||
|
this.creationTime = flowFileCreationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return flowFileUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimestamp() {
|
||||||
|
return creationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClusterNodeIdentifier() {
|
||||||
|
return clusterNodeIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LineageNodeType getNodeType() {
|
||||||
|
return LineageNodeType.FLOWFILE_NODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlowFileUuid() {
|
||||||
|
return flowFileUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 23498723 + flowFileUuid.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof FlowFileNode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FlowFileNode other = (FlowFileNode) obj;
|
||||||
|
return flowFileUuid.equals(other.flowFileUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FlowFile[UUID=" + flowFileUuid + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<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">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>flowfile-packager</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>FlowFile Packager</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.9</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface FlowFilePackager {
|
||||||
|
|
||||||
|
void packageFlowFile(InputStream in, OutputStream out, Map<String, String> attributes, long fileSize) throws IOException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||||
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
|
|
||||||
|
public class FlowFilePackagerV1 implements FlowFilePackager {
|
||||||
|
|
||||||
|
public static final String FILENAME_ATTRIBUTES = "flowfile.attributes";
|
||||||
|
public static final String FILENAME_CONTENT = "flowfile.content";
|
||||||
|
public static final int DEFAULT_TAR_PERMISSIONS = 0644;
|
||||||
|
|
||||||
|
private final int tarPermissions;
|
||||||
|
|
||||||
|
public FlowFilePackagerV1() {
|
||||||
|
this(DEFAULT_TAR_PERMISSIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlowFilePackagerV1(final int tarPermissions) {
|
||||||
|
this.tarPermissions = tarPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packageFlowFile(final InputStream in, final OutputStream out, final Map<String, String> attributes, final long fileSize) throws IOException {
|
||||||
|
try (final TarArchiveOutputStream tout = new TarArchiveOutputStream(out)) {
|
||||||
|
writeAttributesEntry(attributes, tout);
|
||||||
|
writeContentEntry(tout, in, fileSize);
|
||||||
|
tout.finish();
|
||||||
|
tout.flush();
|
||||||
|
tout.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeAttributesEntry(final Map<String, String> attributes, final TarArchiveOutputStream tout) throws IOException {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE properties\n SYSTEM \"http://java.sun.com/dtd/properties.dtd\">\n");
|
||||||
|
sb.append("<properties>");
|
||||||
|
for (final Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||||
|
final String escapedKey = StringEscapeUtils.escapeXml(entry.getKey());
|
||||||
|
final String escapedValue = StringEscapeUtils.escapeXml(entry.getValue());
|
||||||
|
sb.append("\n <entry key=\"").append(escapedKey).append("\">").append(escapedValue).append("</entry>");
|
||||||
|
}
|
||||||
|
sb.append("</properties>");
|
||||||
|
|
||||||
|
final byte[] metaBytes = sb.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
|
final TarArchiveEntry attribEntry = new TarArchiveEntry(FILENAME_ATTRIBUTES);
|
||||||
|
attribEntry.setMode(tarPermissions);
|
||||||
|
attribEntry.setSize(metaBytes.length);
|
||||||
|
tout.putArchiveEntry(attribEntry);
|
||||||
|
tout.write(metaBytes);
|
||||||
|
tout.closeArchiveEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeContentEntry(final TarArchiveOutputStream tarOut, final InputStream inStream, final long fileSize) throws IOException {
|
||||||
|
final TarArchiveEntry entry = new TarArchiveEntry(FILENAME_CONTENT);
|
||||||
|
entry.setMode(tarPermissions);
|
||||||
|
entry.setSize(fileSize);
|
||||||
|
tarOut.putArchiveEntry(entry);
|
||||||
|
final byte[] buffer = new byte[512 << 10];//512KB
|
||||||
|
int bytesRead = 0;
|
||||||
|
while ((bytesRead = inStream.read(buffer)) != -1) { //still more data to read
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
tarOut.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(inStream, tarOut);
|
||||||
|
tarOut.closeArchiveEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long copy(final InputStream source, final OutputStream destination) throws IOException {
|
||||||
|
final byte[] buffer = new byte[8192];
|
||||||
|
int len;
|
||||||
|
long totalCount = 0L;
|
||||||
|
while ((len = source.read(buffer)) > 0) {
|
||||||
|
destination.write(buffer, 0, len);
|
||||||
|
totalCount += len;
|
||||||
|
}
|
||||||
|
return totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Packages a FlowFile, including both its content and its attributes into a
|
||||||
|
* single file that is stream-friendly. The encoding scheme is as such:
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Length Field : indicates the number of Flow File Attributes in the stream
|
||||||
|
* 1 to N times (N=number of Flow File Attributes):
|
||||||
|
* String Field : Flow File Attribute key name
|
||||||
|
* String Field : Flow File Attribute value
|
||||||
|
* Long : 8 bytes indicating the length of the Flow File content
|
||||||
|
* Content : The next M bytes are the content of the Flow File.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Encoding of String Field is as follows:
|
||||||
|
* Length Field : indicates the length of the String
|
||||||
|
* 1 to N bytes (N=String length, determined by previous field, as described above) : The UTF-8 encoded string value.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Encoding of Length Field is as follows:
|
||||||
|
* First 2 bytes: Indicate length. If both bytes = 255, this is a special value indicating that the length is
|
||||||
|
* greater than or equal to 65536 bytes; therefore, the next 4 bytes will indicate the actual length.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note: All byte-order encoding is Network Byte Order (Most Significant Byte
|
||||||
|
* first)
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The following example shows the bytes expected if we were to encode a
|
||||||
|
* FlowFile containing the following attributes where the content is the text
|
||||||
|
* "Hello World!":
|
||||||
|
*
|
||||||
|
* <br><br>
|
||||||
|
* Attributes:
|
||||||
|
* <pre>
|
||||||
|
* +-------+-------+
|
||||||
|
* | Key + Value |
|
||||||
|
* + --------------+
|
||||||
|
* | A | a |
|
||||||
|
* + --------------+
|
||||||
|
* | B | b |
|
||||||
|
* + --------------+
|
||||||
|
* </pre> Content:<br>
|
||||||
|
* Hello World!
|
||||||
|
* <br><br>
|
||||||
|
* Packaged Byte Encoding (In Hexadecimal Form):
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 00 02 00 01 41 00 01 61
|
||||||
|
* 00 01 42 00 01 62 00 00
|
||||||
|
* 00 00 00 00 00 0C 48 65
|
||||||
|
* 6C 6C 6F 20 57 6F 72 6C
|
||||||
|
* 64 21
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class FlowFilePackagerV2 implements FlowFilePackager {
|
||||||
|
|
||||||
|
private static final int MAX_VALUE_2_BYTES = 65535;
|
||||||
|
private final byte[] writeBuffer = new byte[8];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packageFlowFile(final InputStream in, final OutputStream out, final Map<String, String> attributes, final long fileSize) throws IOException {
|
||||||
|
writeFieldLength(out, attributes.size()); //write out the number of attributes
|
||||||
|
for (final Map.Entry<String, String> entry : attributes.entrySet()) { //write out each attribute key/value pair
|
||||||
|
writeString(entry.getKey(), out);
|
||||||
|
writeString(entry.getValue(), out);
|
||||||
|
}
|
||||||
|
writeLong(out, fileSize);//write out length of data
|
||||||
|
copy(in, out);//write out the actual flow file payload
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copy(final InputStream in, final OutputStream out) throws IOException {
|
||||||
|
final byte[] buffer = new byte[65536];
|
||||||
|
int len;
|
||||||
|
while ((len = in.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeString(final String val, final OutputStream out) throws IOException {
|
||||||
|
final byte[] bytes = val.getBytes("UTF-8");
|
||||||
|
writeFieldLength(out, bytes.length);
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeFieldLength(final OutputStream out, final int numBytes) throws IOException {
|
||||||
|
// If the value is less than the max value that can be fit into 2 bytes, just use the
|
||||||
|
// actual value. Otherwise, we will set the first 2 bytes to 255/255 and then use the next
|
||||||
|
// 4 bytes to indicate the real length.
|
||||||
|
if (numBytes < MAX_VALUE_2_BYTES) {
|
||||||
|
writeBuffer[0] = (byte) (numBytes >>> 8);
|
||||||
|
writeBuffer[1] = (byte) (numBytes);
|
||||||
|
out.write(writeBuffer, 0, 2);
|
||||||
|
} else {
|
||||||
|
writeBuffer[0] = (byte) 0xff;
|
||||||
|
writeBuffer[1] = (byte) 0xff;
|
||||||
|
writeBuffer[2] = (byte) (numBytes >>> 24);
|
||||||
|
writeBuffer[3] = (byte) (numBytes >>> 16);
|
||||||
|
writeBuffer[4] = (byte) (numBytes >>> 8);
|
||||||
|
writeBuffer[5] = (byte) (numBytes);
|
||||||
|
out.write(writeBuffer, 0, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLong(final OutputStream out, final long val) throws IOException {
|
||||||
|
writeBuffer[0] = (byte) (val >>> 56);
|
||||||
|
writeBuffer[1] = (byte) (val >>> 48);
|
||||||
|
writeBuffer[2] = (byte) (val >>> 40);
|
||||||
|
writeBuffer[3] = (byte) (val >>> 32);
|
||||||
|
writeBuffer[4] = (byte) (val >>> 24);
|
||||||
|
writeBuffer[5] = (byte) (val >>> 16);
|
||||||
|
writeBuffer[6] = (byte) (val >>> 8);
|
||||||
|
writeBuffer[7] = (byte) (val);
|
||||||
|
out.write(writeBuffer, 0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlowFilePackagerV3 implements FlowFilePackager {
|
||||||
|
|
||||||
|
public static final byte[] MAGIC_HEADER = {'N', 'i', 'F', 'i', 'F', 'F', '3'};
|
||||||
|
private static final int MAX_VALUE_2_BYTES = 65535;
|
||||||
|
private final byte[] writeBuffer = new byte[8];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packageFlowFile(final InputStream in, final OutputStream out, final Map<String, String> attributes, final long fileSize) throws IOException {
|
||||||
|
out.write(MAGIC_HEADER);
|
||||||
|
|
||||||
|
if (attributes == null) {
|
||||||
|
writeFieldLength(out, 0);
|
||||||
|
} else {
|
||||||
|
writeFieldLength(out, attributes.size()); //write out the number of attributes
|
||||||
|
for (final Map.Entry<String, String> entry : attributes.entrySet()) { //write out each attribute key/value pair
|
||||||
|
writeString(entry.getKey(), out);
|
||||||
|
writeString(entry.getValue(), out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeLong(out, fileSize);//write out length of data
|
||||||
|
copy(in, out);//write out the actual flow file payload
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copy(final InputStream in, final OutputStream out) throws IOException {
|
||||||
|
final byte[] buffer = new byte[65536];
|
||||||
|
int len;
|
||||||
|
while ((len = in.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeString(final String val, final OutputStream out) throws IOException {
|
||||||
|
final byte[] bytes = val.getBytes("UTF-8");
|
||||||
|
writeFieldLength(out, bytes.length);
|
||||||
|
out.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeFieldLength(final OutputStream out, final int numBytes) throws IOException {
|
||||||
|
// If the value is less than the max value that can be fit into 2 bytes, just use the
|
||||||
|
// actual value. Otherwise, we will set the first 2 bytes to 255/255 and then use the next
|
||||||
|
// 4 bytes to indicate the real length.
|
||||||
|
if (numBytes < MAX_VALUE_2_BYTES) {
|
||||||
|
writeBuffer[0] = (byte) (numBytes >>> 8);
|
||||||
|
writeBuffer[1] = (byte) (numBytes);
|
||||||
|
out.write(writeBuffer, 0, 2);
|
||||||
|
} else {
|
||||||
|
writeBuffer[0] = (byte) 0xff;
|
||||||
|
writeBuffer[1] = (byte) 0xff;
|
||||||
|
writeBuffer[2] = (byte) (numBytes >>> 24);
|
||||||
|
writeBuffer[3] = (byte) (numBytes >>> 16);
|
||||||
|
writeBuffer[4] = (byte) (numBytes >>> 8);
|
||||||
|
writeBuffer[5] = (byte) (numBytes);
|
||||||
|
out.write(writeBuffer, 0, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLong(final OutputStream out, final long val) throws IOException {
|
||||||
|
writeBuffer[0] = (byte) (val >>> 56);
|
||||||
|
writeBuffer[1] = (byte) (val >>> 48);
|
||||||
|
writeBuffer[2] = (byte) (val >>> 40);
|
||||||
|
writeBuffer[3] = (byte) (val >>> 32);
|
||||||
|
writeBuffer[4] = (byte) (val >>> 24);
|
||||||
|
writeBuffer[5] = (byte) (val >>> 16);
|
||||||
|
writeBuffer[6] = (byte) (val >>> 8);
|
||||||
|
writeBuffer[7] = (byte) (val);
|
||||||
|
out.write(writeBuffer, 0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface FlowFileUnpackager {
|
||||||
|
|
||||||
|
Map<String, String> unpackageFlowFile(InputStream in, OutputStream out) throws IOException;
|
||||||
|
|
||||||
|
boolean hasMoreData() throws IOException;
|
||||||
|
|
||||||
|
}
|
|
@ -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.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||||
|
|
||||||
|
public class FlowFileUnpackagerV1 implements FlowFileUnpackager {
|
||||||
|
|
||||||
|
private int flowFilesRead = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> unpackageFlowFile(final InputStream in, final OutputStream out) throws IOException {
|
||||||
|
flowFilesRead++;
|
||||||
|
final TarArchiveInputStream tarIn = new TarArchiveInputStream(in);
|
||||||
|
final TarArchiveEntry attribEntry = tarIn.getNextTarEntry();
|
||||||
|
if (attribEntry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> attributes;
|
||||||
|
if (attribEntry.getName().equals(FlowFilePackagerV1.FILENAME_ATTRIBUTES)) {
|
||||||
|
attributes = getAttributes(tarIn);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Expected two tar entries: "
|
||||||
|
+ FlowFilePackagerV1.FILENAME_CONTENT + " and "
|
||||||
|
+ FlowFilePackagerV1.FILENAME_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
final TarArchiveEntry contentEntry = tarIn.getNextTarEntry();
|
||||||
|
|
||||||
|
if (contentEntry != null && contentEntry.getName().equals(FlowFilePackagerV1.FILENAME_CONTENT)) {
|
||||||
|
final byte[] buffer = new byte[512 << 10];//512KB
|
||||||
|
int bytesRead = 0;
|
||||||
|
while ((bytesRead = tarIn.read(buffer)) != -1) { //still more data to read
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
} else {
|
||||||
|
throw new IOException("Expected two tar entries: "
|
||||||
|
+ FlowFilePackagerV1.FILENAME_CONTENT + " and "
|
||||||
|
+ FlowFilePackagerV1.FILENAME_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, String> getAttributes(final TarArchiveInputStream stream) throws IOException {
|
||||||
|
|
||||||
|
final Properties props = new Properties();
|
||||||
|
props.loadFromXML(new NonCloseableInputStream(stream));
|
||||||
|
|
||||||
|
final Map<String, String> result = new HashMap<>();
|
||||||
|
for (final Entry<Object, Object> entry : props.entrySet()) {
|
||||||
|
final Object keyObject = entry.getKey();
|
||||||
|
final Object valueObject = entry.getValue();
|
||||||
|
if (!(keyObject instanceof String)) {
|
||||||
|
throw new IOException("Flow file attributes object contains key of type "
|
||||||
|
+ keyObject.getClass().getCanonicalName()
|
||||||
|
+ " but expected java.lang.String");
|
||||||
|
} else if (!(keyObject instanceof String)) {
|
||||||
|
throw new IOException("Flow file attributes object contains value of type "
|
||||||
|
+ keyObject.getClass().getCanonicalName()
|
||||||
|
+ " but expected java.lang.String");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String key = (String) keyObject;
|
||||||
|
final String value = (String) valueObject;
|
||||||
|
result.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMoreData() throws IOException {
|
||||||
|
return flowFilesRead == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class NonCloseableInputStream extends InputStream {
|
||||||
|
|
||||||
|
final InputStream stream;
|
||||||
|
|
||||||
|
public NonCloseableInputStream(final InputStream stream) {
|
||||||
|
this.stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return stream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return stream.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void mark(int readlimit) {
|
||||||
|
stream.mark(readlimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reset() throws IOException {
|
||||||
|
stream.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean markSupported() {
|
||||||
|
return stream.markSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
return stream.skip(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
|
return stream.read(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte b[]) throws IOException {
|
||||||
|
return stream.read(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlowFileUnpackagerV2 implements FlowFileUnpackager {
|
||||||
|
|
||||||
|
private final byte readBuffer[] = new byte[8192];
|
||||||
|
private Map<String, String> nextAttributes = null;
|
||||||
|
private boolean haveReadSomething = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMoreData() throws IOException {
|
||||||
|
return nextAttributes != null || !haveReadSomething;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, String> readAttributes(final InputStream in) throws IOException {
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
final Integer numAttributes = readFieldLength(in); //read number of attributes
|
||||||
|
if (numAttributes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (numAttributes == 0) {
|
||||||
|
throw new IOException("flow files cannot have zero attributes");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < numAttributes; i++) { //read each attribute key/value pair
|
||||||
|
final String key = readString(in);
|
||||||
|
final String value = readString(in);
|
||||||
|
attributes.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> unpackageFlowFile(final InputStream in, final OutputStream out) throws IOException {
|
||||||
|
final Map<String, String> attributes;
|
||||||
|
if (nextAttributes != null) {
|
||||||
|
attributes = nextAttributes;
|
||||||
|
} else {
|
||||||
|
attributes = readAttributes(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long expectedNumBytes = readLong(in); // read length of payload
|
||||||
|
copy(in, out, expectedNumBytes); // read payload
|
||||||
|
|
||||||
|
nextAttributes = readAttributes(in);
|
||||||
|
haveReadSomething = true;
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String readString(final InputStream in) throws IOException {
|
||||||
|
final Integer numBytes = readFieldLength(in);
|
||||||
|
if (numBytes == null) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
final byte[] bytes = new byte[numBytes];
|
||||||
|
fillBuffer(in, bytes, numBytes);
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillBuffer(final InputStream in, final byte[] buffer, final int length) throws IOException {
|
||||||
|
int bytesRead;
|
||||||
|
int totalBytesRead = 0;
|
||||||
|
while ((bytesRead = in.read(buffer, totalBytesRead, length - totalBytesRead)) > 0) {
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
}
|
||||||
|
if (totalBytesRead != length) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long copy(final InputStream in, final OutputStream out, final long numBytes) throws IOException {
|
||||||
|
int bytesRead;
|
||||||
|
long totalBytesRead = 0L;
|
||||||
|
while ((bytesRead = in.read(readBuffer, 0, (int) Math.min(readBuffer.length, numBytes - totalBytesRead))) > 0) {
|
||||||
|
out.write(readBuffer, 0, bytesRead);
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalBytesRead < numBytes) {
|
||||||
|
throw new EOFException("Expected " + numBytes + " but received " + totalBytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long readLong(final InputStream in) throws IOException {
|
||||||
|
fillBuffer(in, readBuffer, 8);
|
||||||
|
return (((long) readBuffer[0] << 56)
|
||||||
|
+ ((long) (readBuffer[1] & 255) << 48)
|
||||||
|
+ ((long) (readBuffer[2] & 255) << 40)
|
||||||
|
+ ((long) (readBuffer[3] & 255) << 32)
|
||||||
|
+ ((long) (readBuffer[4] & 255) << 24)
|
||||||
|
+ ((readBuffer[5] & 255) << 16)
|
||||||
|
+ ((readBuffer[6] & 255) << 8)
|
||||||
|
+ ((readBuffer[7] & 255)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer readFieldLength(final InputStream in) throws IOException {
|
||||||
|
final int firstValue = in.read();
|
||||||
|
final int secondValue = in.read();
|
||||||
|
if (firstValue < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (secondValue < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
if (firstValue == 0xff && secondValue == 0xff) {
|
||||||
|
int ch1 = in.read();
|
||||||
|
int ch2 = in.read();
|
||||||
|
int ch3 = in.read();
|
||||||
|
int ch4 = in.read();
|
||||||
|
if ((ch1 | ch2 | ch3 | ch4) < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
|
||||||
|
} else {
|
||||||
|
return ((firstValue << 8) + (secondValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlowFileUnpackagerV3 implements FlowFileUnpackager {
|
||||||
|
|
||||||
|
private byte[] nextHeader = null;
|
||||||
|
private boolean haveReadSomething = false;
|
||||||
|
private final byte readBuffer[] = new byte[8192];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMoreData() throws IOException {
|
||||||
|
return nextHeader != null || !haveReadSomething;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] readHeader(final InputStream in) throws IOException {
|
||||||
|
final byte[] header = new byte[FlowFilePackagerV3.MAGIC_HEADER.length];
|
||||||
|
for (int i = 0; i < header.length; i++) {
|
||||||
|
final int next = in.read();
|
||||||
|
if (next < 0) {
|
||||||
|
if (i == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Not in FlowFile-v3 format");
|
||||||
|
}
|
||||||
|
header[i] = (byte) (next & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> unpackageFlowFile(final InputStream in, final OutputStream out) throws IOException {
|
||||||
|
final byte[] header = (nextHeader == null) ? readHeader(in) : nextHeader;
|
||||||
|
if (!Arrays.equals(header, FlowFilePackagerV3.MAGIC_HEADER)) {
|
||||||
|
throw new IOException("Not in FlowFile-v3 format");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> attributes = readAttributes(in);
|
||||||
|
final long expectedNumBytes = readLong(in); // read length of payload
|
||||||
|
copy(in, out, expectedNumBytes); // read payload
|
||||||
|
|
||||||
|
nextHeader = readHeader(in);
|
||||||
|
haveReadSomething = true;
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, String> readAttributes(final InputStream in) throws IOException {
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
final Integer numAttributes = readFieldLength(in); //read number of attributes
|
||||||
|
if (numAttributes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (numAttributes == 0) {
|
||||||
|
throw new IOException("flow files cannot have zero attributes");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < numAttributes; i++) { //read each attribute key/value pair
|
||||||
|
final String key = readString(in);
|
||||||
|
final String value = readString(in);
|
||||||
|
attributes.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String readString(final InputStream in) throws IOException {
|
||||||
|
final Integer numBytes = readFieldLength(in);
|
||||||
|
if (numBytes == null) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
final byte[] bytes = new byte[numBytes];
|
||||||
|
fillBuffer(in, bytes, numBytes);
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillBuffer(final InputStream in, final byte[] buffer, final int length) throws IOException {
|
||||||
|
int bytesRead;
|
||||||
|
int totalBytesRead = 0;
|
||||||
|
while ((bytesRead = in.read(buffer, totalBytesRead, length - totalBytesRead)) > 0) {
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
}
|
||||||
|
if (totalBytesRead != length) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long copy(final InputStream in, final OutputStream out, final long numBytes) throws IOException {
|
||||||
|
int bytesRead;
|
||||||
|
long totalBytesRead = 0L;
|
||||||
|
while ((bytesRead = in.read(readBuffer, 0, (int) Math.min(readBuffer.length, numBytes - totalBytesRead))) > 0) {
|
||||||
|
out.write(readBuffer, 0, bytesRead);
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalBytesRead < numBytes) {
|
||||||
|
throw new EOFException("Expected " + numBytes + " but received " + totalBytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long readLong(final InputStream in) throws IOException {
|
||||||
|
fillBuffer(in, readBuffer, 8);
|
||||||
|
return (((long) readBuffer[0] << 56)
|
||||||
|
+ ((long) (readBuffer[1] & 255) << 48)
|
||||||
|
+ ((long) (readBuffer[2] & 255) << 40)
|
||||||
|
+ ((long) (readBuffer[3] & 255) << 32)
|
||||||
|
+ ((long) (readBuffer[4] & 255) << 24)
|
||||||
|
+ ((readBuffer[5] & 255) << 16)
|
||||||
|
+ ((readBuffer[6] & 255) << 8)
|
||||||
|
+ ((readBuffer[7] & 255)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer readFieldLength(final InputStream in) throws IOException {
|
||||||
|
final int firstValue = in.read();
|
||||||
|
final int secondValue = in.read();
|
||||||
|
if (firstValue < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (secondValue < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
if (firstValue == 0xff && secondValue == 0xff) {
|
||||||
|
int ch1 = in.read();
|
||||||
|
int ch2 = in.read();
|
||||||
|
int ch3 = in.read();
|
||||||
|
int ch4 = in.read();
|
||||||
|
if ((ch1 | ch2 | ch3 | ch4) < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4));
|
||||||
|
} else {
|
||||||
|
return ((firstValue << 8) + (secondValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class Unpackage {
|
||||||
|
|
||||||
|
private static void printUsage() {
|
||||||
|
System.out.println("java " + Unpackage.class.getCanonicalName() + " <version> <input file 1> [<input file 2> <input file 3> ... <input file N>]");
|
||||||
|
System.out.println("<version> : The version of the FlowFile Package format. Valid values are 1, 2, 3");
|
||||||
|
System.out.println("<input file X> : The FlowFile package to unpack");
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws IOException {
|
||||||
|
if (args.length < 2) {
|
||||||
|
printUsage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String version = args[0];
|
||||||
|
|
||||||
|
int inputFileCount = 0;
|
||||||
|
int outputFileCount = 0;
|
||||||
|
|
||||||
|
for (int i = 1; i < args.length; i++) {
|
||||||
|
final String filename = args[i];
|
||||||
|
final File inFile = new File(filename);
|
||||||
|
|
||||||
|
if (inFile.isDirectory()) {
|
||||||
|
System.out.println("WARNING: input file " + inFile + " is a directory; skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inFile.exists() || !inFile.canRead()) {
|
||||||
|
System.out.println("ERROR: unable to read file " + inFile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final File outputDir = new File(inFile.getAbsolutePath() + ".unpacked");
|
||||||
|
if (!outputDir.exists() && !outputDir.mkdir()) {
|
||||||
|
System.out.println("ERROR: Unable to create directory " + outputDir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final File tempFile = new File(outputDir, ".temp." + UUID.randomUUID().toString() + ".unpackage");
|
||||||
|
inputFileCount++;
|
||||||
|
try (final FileInputStream fis = new FileInputStream(inFile);
|
||||||
|
final BufferedInputStream bufferedIn = new BufferedInputStream(fis)) {
|
||||||
|
|
||||||
|
final FlowFileUnpackager unpackager = createUnpackager(version);
|
||||||
|
while (unpackager.hasMoreData()) {
|
||||||
|
outputFileCount++;
|
||||||
|
final Map<String, String> attributes;
|
||||||
|
|
||||||
|
try (final FileOutputStream fos = new FileOutputStream(tempFile);
|
||||||
|
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fos)) {
|
||||||
|
attributes = unpackager.unpackageFlowFile(bufferedIn, bufferedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
String outputFilename = attributes.get("filename");
|
||||||
|
if (outputFilename == null) {
|
||||||
|
outputFilename = attributes.get("nf.file.name");
|
||||||
|
}
|
||||||
|
|
||||||
|
final File outputFile = new File(outputDir, outputFilename);
|
||||||
|
tempFile.renameTo(outputFile);
|
||||||
|
|
||||||
|
final File attributeFilename = new File(outputDir, outputFilename + ".attributes");
|
||||||
|
try (final FileOutputStream fos = new FileOutputStream(attributeFilename);
|
||||||
|
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fos)) {
|
||||||
|
|
||||||
|
for (final Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||||
|
bufferedOut.write((entry.getKey() + "=" + entry.getValue() + "\n").getBytes("UTF-8"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Unpacked " + inputFileCount + " packages into " + outputFileCount + " files");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlowFileUnpackager createUnpackager(final String version) {
|
||||||
|
switch (version) {
|
||||||
|
case "1":
|
||||||
|
return new FlowFileUnpackagerV1();
|
||||||
|
case "2":
|
||||||
|
return new FlowFileUnpackagerV2();
|
||||||
|
case "3":
|
||||||
|
return new FlowFileUnpackagerV3();
|
||||||
|
default:
|
||||||
|
System.out.println("ERROR: Invalid version: " + version + "; must be 1, 2, or 3");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestPackageUnpackageV3 {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws IOException {
|
||||||
|
final FlowFilePackager packager = new FlowFilePackagerV3();
|
||||||
|
final FlowFileUnpackager unpackager = new FlowFileUnpackagerV3();
|
||||||
|
|
||||||
|
final byte[] data = "Hello, World!".getBytes("UTF-8");
|
||||||
|
final Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("abc", "cba");
|
||||||
|
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
final ByteArrayInputStream in = new ByteArrayInputStream(data);
|
||||||
|
packager.packageFlowFile(in, baos, map, data.length);
|
||||||
|
|
||||||
|
final byte[] encoded = baos.toByteArray();
|
||||||
|
final ByteArrayInputStream encodedIn = new ByteArrayInputStream(encoded);
|
||||||
|
final ByteArrayOutputStream decodedOut = new ByteArrayOutputStream();
|
||||||
|
final Map<String, String> unpackagedAttributes = unpackager.unpackageFlowFile(encodedIn, decodedOut);
|
||||||
|
final byte[] decoded = decodedOut.toByteArray();
|
||||||
|
|
||||||
|
assertEquals(map, unpackagedAttributes);
|
||||||
|
assertTrue(Arrays.equals(data, decoded));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<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">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>naive-search-ring-buffer</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>NiFi Ring Buffer</name>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* A RingBuffer that can be used to scan byte sequences for subsequences.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This class implements an efficient naive search algorithm, which allows the
|
||||||
|
* user of the library to identify byte sequences in a stream on-the-fly so that
|
||||||
|
* the stream can be segmented without having to buffer the data.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The intended usage paradigm is:
|
||||||
|
* <code>
|
||||||
|
* <pre>
|
||||||
|
* final byte[] searchSequence = ...;
|
||||||
|
* final CircularBuffer buffer = new CircularBuffer(searchSequence);
|
||||||
|
* while ((int nextByte = in.read()) > 0) {
|
||||||
|
* if ( buffer.addAndCompare(nextByte) ) {
|
||||||
|
* // This byte is the last byte in the given sequence
|
||||||
|
* } else {
|
||||||
|
* // This byte does not complete the given sequence
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* </code>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class NaiveSearchRingBuffer {
|
||||||
|
|
||||||
|
private final byte[] lookingFor;
|
||||||
|
private final int[] buffer;
|
||||||
|
private int insertionPointer = 0;
|
||||||
|
private int bufferSize = 0;
|
||||||
|
|
||||||
|
public NaiveSearchRingBuffer(final byte[] lookingFor) {
|
||||||
|
this.lookingFor = lookingFor;
|
||||||
|
this.buffer = new int[lookingFor.length];
|
||||||
|
Arrays.fill(buffer, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the contents of the internal buffer, which represents the last X
|
||||||
|
* bytes added to the buffer, where X is the minimum of the number of bytes
|
||||||
|
* added to the buffer or the length of the byte sequence for which we are
|
||||||
|
* looking
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public byte[] getBufferContents() {
|
||||||
|
final int contentLength = Math.min(lookingFor.length, bufferSize);
|
||||||
|
final byte[] contents = new byte[contentLength];
|
||||||
|
for (int i = 0; i < contentLength; i++) {
|
||||||
|
final byte nextByte = (byte) buffer[(insertionPointer + i) % lookingFor.length];
|
||||||
|
contents[i] = nextByte;
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the oldest byte in the buffer
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getOldestByte() {
|
||||||
|
return buffer[insertionPointer];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the number of bytes that have been added to
|
||||||
|
* the buffer is at least equal to the length of the byte sequence for which
|
||||||
|
* we are searching
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isFilled() {
|
||||||
|
return bufferSize >= buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the internal buffer so that a new search may begin
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
Arrays.fill(buffer, -1);
|
||||||
|
insertionPointer = 0;
|
||||||
|
bufferSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given byte to the buffer and notify whether or not the byte
|
||||||
|
* completes the desired byte sequence.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @return <code>true</code> if this byte completes the byte sequence,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean addAndCompare(final byte data) {
|
||||||
|
buffer[insertionPointer] = data;
|
||||||
|
insertionPointer = (insertionPointer + 1) % lookingFor.length;
|
||||||
|
|
||||||
|
bufferSize++;
|
||||||
|
if (bufferSize < lookingFor.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < lookingFor.length; i++) {
|
||||||
|
final byte compare = (byte) buffer[(insertionPointer + i) % lookingFor.length];
|
||||||
|
if (compare != lookingFor[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestNaiveSearchRingBuffer {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddAndCompare() {
|
||||||
|
final byte[] pattern = new byte[]{
|
||||||
|
'\r', '0', 38, 48
|
||||||
|
};
|
||||||
|
|
||||||
|
final byte[] search = new byte[]{
|
||||||
|
'\r', '0', 38, 58, 58, 83, 78, '\r', '0', 38, 48, 83, 92, 78, 4, 38
|
||||||
|
};
|
||||||
|
|
||||||
|
final NaiveSearchRingBuffer circ = new NaiveSearchRingBuffer(pattern);
|
||||||
|
int counter = -1;
|
||||||
|
for (final byte b : search) {
|
||||||
|
counter++;
|
||||||
|
final boolean matched = circ.addAndCompare(b);
|
||||||
|
if (counter == 10) {
|
||||||
|
assertTrue(matched);
|
||||||
|
} else {
|
||||||
|
assertFalse(matched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetOldestByte() {
|
||||||
|
final byte[] pattern = new byte[]{
|
||||||
|
'\r', '0', 38, 48
|
||||||
|
};
|
||||||
|
|
||||||
|
final byte[] search = new byte[]{
|
||||||
|
'\r', '0', 38, 58, 58, 83, 78, (byte) 223, (byte) 227, (byte) 250, '\r', '0', 38, 48, 83, 92, 78, 4, 38
|
||||||
|
};
|
||||||
|
|
||||||
|
final NaiveSearchRingBuffer circ = new NaiveSearchRingBuffer(pattern);
|
||||||
|
int counter = -1;
|
||||||
|
for (final byte b : search) {
|
||||||
|
counter++;
|
||||||
|
final boolean matched = circ.addAndCompare(b);
|
||||||
|
if (counter == 13) {
|
||||||
|
assertTrue(matched);
|
||||||
|
} else {
|
||||||
|
assertFalse(matched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
<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">
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nifi-expression-language</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>NiFi Expression Language</name>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-runtime</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-api</artifactId>
|
||||||
|
<version>[0.0.1-SNAPSHOT, 1.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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 AttributeExpressionLexer;
|
||||||
|
|
||||||
|
@header {
|
||||||
|
package org.apache.nifi.attribute.expression.language.antlr;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@rulecatch {
|
||||||
|
catch(final Exception e) {
|
||||||
|
throw new AttributeExpressionLanguageParsingException(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 AttributeExpressionLanguageParsingException(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 AttributeExpressionLanguageParsingException(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PUNCTUATION & SPECIAL CHARACTERS
|
||||||
|
WHITESPACE : (' '|'\t'|'\n'|'\r')+ { $channel = HIDDEN; };
|
||||||
|
COMMENT : '#' ( ~('\n') )* '\n' { $channel = HIDDEN; };
|
||||||
|
|
||||||
|
DOLLAR : '$';
|
||||||
|
LPAREN : '(';
|
||||||
|
RPAREN : ')';
|
||||||
|
LBRACE : '{';
|
||||||
|
RBRACE : '}';
|
||||||
|
COLON : ':';
|
||||||
|
COMMA : ',';
|
||||||
|
DOT : '.';
|
||||||
|
SEMICOLON : ';';
|
||||||
|
NUMBER : ('0'..'9')+;
|
||||||
|
|
||||||
|
TRUE : 'true';
|
||||||
|
FALSE : 'false';
|
||||||
|
|
||||||
|
//
|
||||||
|
// FUNCTION NAMES
|
||||||
|
//
|
||||||
|
|
||||||
|
// ATTRIBUTE KEY SELECTION FUNCTIONS
|
||||||
|
ANY_ATTRIBUTE : 'anyAttribute';
|
||||||
|
ANY_MATCHING_ATTRIBUTE : 'anyMatchingAttribute';
|
||||||
|
ALL_ATTRIBUTES : 'allAttributes';
|
||||||
|
ALL_MATCHING_ATTRIBUTES : 'allMatchingAttributes';
|
||||||
|
ANY_DELINEATED_VALUE : 'anyDelineatedValue';
|
||||||
|
ALL_DELINEATED_VALUES : 'allDelineatedValues';
|
||||||
|
|
||||||
|
// NO-SUBJECT FUNCTIONS
|
||||||
|
NEXT_INT : 'nextInt';
|
||||||
|
IP : 'ip';
|
||||||
|
UUID : 'UUID';
|
||||||
|
HOSTNAME : 'hostname'; // requires boolean arg: prefer FQDN
|
||||||
|
NOW : 'now';
|
||||||
|
|
||||||
|
|
||||||
|
// 0 arg functions
|
||||||
|
TO_UPPER : 'toUpper';
|
||||||
|
TO_LOWER : 'toLower';
|
||||||
|
TO_STRING : 'toString';
|
||||||
|
LENGTH : 'length';
|
||||||
|
TRIM : 'trim';
|
||||||
|
IS_NULL : 'isNull';
|
||||||
|
NOT_NULL : 'notNull';
|
||||||
|
TO_NUMBER : 'toNumber';
|
||||||
|
URL_ENCODE : 'urlEncode';
|
||||||
|
URL_DECODE : 'urlDecode';
|
||||||
|
NOT : 'not';
|
||||||
|
|
||||||
|
// 1 arg functions
|
||||||
|
SUBSTRING_AFTER : 'substringAfter';
|
||||||
|
SUBSTRING_BEFORE : 'substringBefore';
|
||||||
|
SUBSTRING_AFTER_LAST : 'substringAfterLast';
|
||||||
|
SUBSTRING_BEFORE_LAST : 'substringBeforeLast';
|
||||||
|
STARTS_WITH : 'startsWith';
|
||||||
|
ENDS_WITH : 'endsWith';
|
||||||
|
CONTAINS : 'contains';
|
||||||
|
PREPEND : 'prepend';
|
||||||
|
APPEND : 'append';
|
||||||
|
INDEX_OF : 'indexOf';
|
||||||
|
LAST_INDEX_OF : 'lastIndexOf';
|
||||||
|
REPLACE_NULL : 'replaceNull';
|
||||||
|
FIND : 'find'; // regex
|
||||||
|
MATCHES : 'matches'; // regex
|
||||||
|
EQUALS : 'equals';
|
||||||
|
EQUALS_IGNORE_CASE : 'equalsIgnoreCase';
|
||||||
|
GREATER_THAN : 'gt';
|
||||||
|
LESS_THAN : 'lt';
|
||||||
|
GREATER_THAN_OR_EQUAL : 'ge';
|
||||||
|
LESS_THAN_OR_EQUAL : 'le';
|
||||||
|
FORMAT : 'format'; // takes string date format; uses SimpleDateFormat
|
||||||
|
TO_DATE : 'toDate'; // takes string date format; converts the subject to a Long based on the date format
|
||||||
|
MOD : 'mod';
|
||||||
|
PLUS : 'plus';
|
||||||
|
MINUS : 'minus';
|
||||||
|
MULTIPLY : 'multiply';
|
||||||
|
DIVIDE : 'divide';
|
||||||
|
TO_RADIX : 'toRadix';
|
||||||
|
OR : 'or';
|
||||||
|
AND : 'and';
|
||||||
|
|
||||||
|
|
||||||
|
// 2 arg functions
|
||||||
|
SUBSTRING : 'substring';
|
||||||
|
REPLACE : 'replace';
|
||||||
|
REPLACE_ALL : 'replaceAll';
|
||||||
|
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
ATTRIBUTE_NAME : (
|
||||||
|
~('$' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ':' | ';' | '/' | '*' | '\'' | ' ' | '\t' | '\r' | '\n' | '0'..'9')
|
||||||
|
~('$' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ':' | ';' | '/' | '*' | '\'' | ' ' | '\t' | '\r' | '\n')*
|
||||||
|
);
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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 AttributeExpressionParser;
|
||||||
|
|
||||||
|
options {
|
||||||
|
output=AST;
|
||||||
|
tokenVocab=AttributeExpressionLexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens {
|
||||||
|
QUERY;
|
||||||
|
ATTRIBUTE_REFERENCE;
|
||||||
|
ATTR_NAME;
|
||||||
|
FUNCTION_CALL;
|
||||||
|
EXPRESSION;
|
||||||
|
MULTI_ATTRIBUTE_REFERENCE;
|
||||||
|
QUOTED_ATTR_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@header {
|
||||||
|
package org.apache.nifi.attribute.expression.language.antlr;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 AttributeExpressionLanguageParsingException(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 AttributeExpressionLanguageParsingException(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions that return Strings
|
||||||
|
zeroArgString : (TO_UPPER | TO_LOWER | TRIM | TO_STRING | URL_ENCODE | URL_DECODE) LPAREN! RPAREN!;
|
||||||
|
oneArgString : ((SUBSTRING_BEFORE | SUBSTRING_BEFORE_LAST | SUBSTRING_AFTER | SUBSTRING_AFTER_LAST | REPLACE_NULL |
|
||||||
|
PREPEND | APPEND | FORMAT | STARTS_WITH | ENDS_WITH | CONTAINS) LPAREN! anyArg RPAREN!) |
|
||||||
|
(TO_RADIX LPAREN! anyArg (COMMA! anyArg)? RPAREN!);
|
||||||
|
twoArgString : ((REPLACE | REPLACE_ALL) LPAREN! anyArg COMMA! anyArg RPAREN!) |
|
||||||
|
(SUBSTRING LPAREN! anyArg (COMMA! anyArg)? RPAREN!);
|
||||||
|
|
||||||
|
|
||||||
|
// functions that return Booleans
|
||||||
|
zeroArgBool : (IS_NULL | NOT_NULL | NOT) LPAREN! RPAREN!;
|
||||||
|
oneArgBool : ((FIND | MATCHES | EQUALS_IGNORE_CASE) LPAREN! anyArg RPAREN!) |
|
||||||
|
(GREATER_THAN | LESS_THAN | GREATER_THAN_OR_EQUAL | LESS_THAN_OR_EQUAL) LPAREN! anyArg RPAREN! |
|
||||||
|
(EQUALS) LPAREN! anyArg RPAREN! |
|
||||||
|
(AND | OR) LPAREN! anyArg RPAREN!;
|
||||||
|
|
||||||
|
|
||||||
|
// functions that return Numbers
|
||||||
|
zeroArgNum : (LENGTH | TO_NUMBER) LPAREN! RPAREN!;
|
||||||
|
oneArgNum : ((INDEX_OF | LAST_INDEX_OF) LPAREN! anyArg RPAREN!) |
|
||||||
|
(TO_DATE LPAREN! anyArg? RPAREN!) |
|
||||||
|
((MOD | PLUS | MINUS | MULTIPLY | DIVIDE) LPAREN! anyArg RPAREN!);
|
||||||
|
|
||||||
|
stringFunctionRef : zeroArgString | oneArgString | twoArgString;
|
||||||
|
booleanFunctionRef : zeroArgBool | oneArgBool;
|
||||||
|
numberFunctionRef : zeroArgNum | oneArgNum;
|
||||||
|
|
||||||
|
anyArg : NUMBER | numberFunctionRef | STRING_LITERAL | zeroArgString | oneArgString | twoArgString | booleanLiteral | zeroArgBool | oneArgBool | expression;
|
||||||
|
stringArg : STRING_LITERAL | zeroArgString | oneArgString | twoArgString | expression;
|
||||||
|
functionRef : stringFunctionRef | booleanFunctionRef | numberFunctionRef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Attribute Reference
|
||||||
|
subject : attrName | expression;
|
||||||
|
attrName : singleAttrName | multiAttrName;
|
||||||
|
|
||||||
|
singleAttrRef : ATTRIBUTE_NAME | STRING_LITERAL;
|
||||||
|
singleAttrName : singleAttrRef ->
|
||||||
|
^(ATTR_NAME singleAttrRef);
|
||||||
|
|
||||||
|
|
||||||
|
multiAttrFunction : ANY_ATTRIBUTE | ANY_MATCHING_ATTRIBUTE | ALL_ATTRIBUTES | ALL_MATCHING_ATTRIBUTES | ANY_DELINEATED_VALUE | ALL_DELINEATED_VALUES;
|
||||||
|
multiAttrName : multiAttrFunction LPAREN stringArg (COMMA stringArg)* RPAREN ->
|
||||||
|
^(MULTI_ATTRIBUTE_REFERENCE multiAttrFunction stringArg*);
|
||||||
|
|
||||||
|
attributeRef : subject ->
|
||||||
|
^(ATTRIBUTE_REFERENCE subject);
|
||||||
|
|
||||||
|
|
||||||
|
functionCall : functionRef ->
|
||||||
|
^(FUNCTION_CALL functionRef);
|
||||||
|
|
||||||
|
booleanLiteral : TRUE | FALSE;
|
||||||
|
zeroArgStandaloneFunction : (IP | UUID | NOW | NEXT_INT | HOSTNAME) LPAREN! RPAREN!;
|
||||||
|
oneArgStandaloneFunction : HOSTNAME^ LPAREN! booleanLiteral RPAREN!;
|
||||||
|
standaloneFunction : zeroArgStandaloneFunction | oneArgStandaloneFunction;
|
||||||
|
|
||||||
|
attributeRefOrFunctionCall : (attributeRef | standaloneFunction);
|
||||||
|
|
||||||
|
expression : DOLLAR LBRACE attributeRefOrFunctionCall (COLON functionCall)* RBRACE ->
|
||||||
|
^(EXPRESSION attributeRefOrFunctionCall functionCall*);
|
||||||
|
|
||||||
|
query : expression EOF ->
|
||||||
|
^(QUERY expression);
|
|
@ -0,0 +1,72 @@
|
||||||
|
ALL_ATTRIBUTES=4
|
||||||
|
ALL_DELINEATED_VALUES=5
|
||||||
|
ALL_MATCHING_ATTRIBUTES=6
|
||||||
|
AND=7
|
||||||
|
ANY_ATTRIBUTE=8
|
||||||
|
ANY_DELINEATED_VALUE=9
|
||||||
|
ANY_MATCHING_ATTRIBUTE=10
|
||||||
|
APPEND=11
|
||||||
|
ATTRIBUTE_NAME=12
|
||||||
|
CEIL=13
|
||||||
|
COLON=14
|
||||||
|
COMMA=15
|
||||||
|
CONTAINS=16
|
||||||
|
DIVIDE=17
|
||||||
|
DOLLAR=18
|
||||||
|
DOT=19
|
||||||
|
ENDS_WITH=20
|
||||||
|
EQUALS=21
|
||||||
|
EQUALS_IGNORE_CASE=22
|
||||||
|
FALSE=23
|
||||||
|
FIND=24
|
||||||
|
FLOOR=25
|
||||||
|
FORMAT=26
|
||||||
|
GREATER_THAN=27
|
||||||
|
GREATER_THAN_OR_EQUAL=28
|
||||||
|
HOSTNAME=29
|
||||||
|
INDEX_OF=30
|
||||||
|
IP=31
|
||||||
|
IS_NULL=32
|
||||||
|
LAST_INDEX_OF=33
|
||||||
|
LBRACE=34
|
||||||
|
LENGTH=35
|
||||||
|
LESS_THAN=36
|
||||||
|
LESS_THAN_OR_EQUAL=37
|
||||||
|
LPAREN=38
|
||||||
|
MATCHES=39
|
||||||
|
MINUS=40
|
||||||
|
MOD=41
|
||||||
|
MULTIPLY=42
|
||||||
|
NEXT_INT=43
|
||||||
|
NOT=44
|
||||||
|
NOT_NULL=45
|
||||||
|
NOW=46
|
||||||
|
NUMBER=47
|
||||||
|
OR=48
|
||||||
|
PLUS=49
|
||||||
|
PREPEND=50
|
||||||
|
RBRACE=51
|
||||||
|
REPLACE=52
|
||||||
|
REPLACE_ALL=53
|
||||||
|
REPLACE_NULL=54
|
||||||
|
RPAREN=55
|
||||||
|
SEMICOLON=56
|
||||||
|
STARTS_WITH=57
|
||||||
|
STRING_LITERAL=58
|
||||||
|
SUBSTRING=59
|
||||||
|
SUBSTRING_AFTER=60
|
||||||
|
SUBSTRING_AFTER_LAST=61
|
||||||
|
SUBSTRING_BEFORE=62
|
||||||
|
SUBSTRING_BEFORE_LAST=63
|
||||||
|
TO_DATE=64
|
||||||
|
TO_LOWER=65
|
||||||
|
TO_NUMBER=66
|
||||||
|
TO_RADIX=67
|
||||||
|
TO_STRING=68
|
||||||
|
TO_UPPER=69
|
||||||
|
TRIM=70
|
||||||
|
TRUE=71
|
||||||
|
URL_DECODE=72
|
||||||
|
URL_ENCODE=73
|
||||||
|
UUID=74
|
||||||
|
WHITESPACE=75
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeValueDecorator;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
|
||||||
|
public class EmptyPreparedQuery implements PreparedQuery {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
EmptyPreparedQuery(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions() throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final FlowFile flowFile) throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(Map<String, String> attributes) throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(Map<String, String> attributes, AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeValueDecorator;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
|
||||||
|
public interface PreparedQuery {
|
||||||
|
|
||||||
|
String evaluateExpressions(FlowFile flowFile, AttributeValueDecorator decorator) throws ProcessException;
|
||||||
|
|
||||||
|
String evaluateExpressions() throws ProcessException;
|
||||||
|
|
||||||
|
String evaluateExpressions(AttributeValueDecorator decorator) throws ProcessException;
|
||||||
|
|
||||||
|
String evaluateExpressions(FlowFile flowFile) throws ProcessException;
|
||||||
|
|
||||||
|
String evaluateExpressions(Map<String, String> attributes) throws ProcessException;
|
||||||
|
|
||||||
|
String evaluateExpressions(Map<String, String> attributes, AttributeValueDecorator decorator) throws ProcessException;
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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.attribute.expression.language;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression;
|
||||||
|
import org.apache.nifi.expression.AttributeValueDecorator;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
|
||||||
|
public class StandardAttributeExpression implements AttributeExpression {
|
||||||
|
|
||||||
|
private final Query query;
|
||||||
|
|
||||||
|
public StandardAttributeExpression(final Query query) {
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return query.getResultType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluate() throws ProcessException {
|
||||||
|
return evaluate((AttributeValueDecorator) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluate(final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
return evaluate(null, decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluate(final FlowFile flowFile) throws ProcessException {
|
||||||
|
return evaluate(flowFile, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluate(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
final Object evaluationResult = query.evaluate(flowFile).getValue();
|
||||||
|
if (evaluationResult == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = evaluationResult.toString();
|
||||||
|
if (decorator != null) {
|
||||||
|
result = decorator.decorate(result);
|
||||||
|
}
|
||||||
|
return Query.unescape(result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException;
|
||||||
|
import org.apache.nifi.expression.AttributeExpression;
|
||||||
|
import org.apache.nifi.expression.ExpressionLanguageCompiler;
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class StandardExpressionLanguageCompiler implements ExpressionLanguageCompiler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeExpression compile(final String expression) throws IllegalArgumentException {
|
||||||
|
try {
|
||||||
|
return new StandardAttributeExpression(Query.compile(expression));
|
||||||
|
} catch (final AttributeExpressionLanguageParsingException e) {
|
||||||
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidExpression(final String expression) {
|
||||||
|
return Query.isValidExpression(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String validateExpression(final String expression, final boolean allowSurroundingCharacters) {
|
||||||
|
try {
|
||||||
|
Query.validateExpression(expression, allowSurroundingCharacters);
|
||||||
|
return null;
|
||||||
|
} catch (final AttributeExpressionLanguageParsingException aelpe) {
|
||||||
|
return aelpe.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType(final String expression) throws IllegalArgumentException {
|
||||||
|
try {
|
||||||
|
return Query.getResultType(expression);
|
||||||
|
} catch (final AttributeExpressionLanguageParsingException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeValueDecorator;
|
||||||
|
import org.apache.nifi.flowfile.FlowFile;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
|
||||||
|
import org.antlr.runtime.tree.Tree;
|
||||||
|
|
||||||
|
public class StandardPreparedQuery implements PreparedQuery {
|
||||||
|
|
||||||
|
private final List<String> queryStrings;
|
||||||
|
private final Map<String, Tree> trees;
|
||||||
|
|
||||||
|
public StandardPreparedQuery(final List<String> queryStrings, final Map<String, Tree> trees) {
|
||||||
|
this.queryStrings = new ArrayList<>(queryStrings);
|
||||||
|
this.trees = new HashMap<>(trees);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(Map<String, String> attributes) throws ProcessException {
|
||||||
|
return evaluateExpressions(attributes, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final Map<String, String> attributes, final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (final String val : queryStrings) {
|
||||||
|
final Tree tree = trees.get(val);
|
||||||
|
if (tree == null) {
|
||||||
|
sb.append(val);
|
||||||
|
} else {
|
||||||
|
final String evaluated = Query.evaluateExpression(tree, val, attributes, decorator);
|
||||||
|
if (evaluated != null) {
|
||||||
|
sb.append(evaluated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
final Map<String, String> expressionMap = Query.createExpressionMap(flowFile);
|
||||||
|
return evaluateExpressions(expressionMap, decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions() throws ProcessException {
|
||||||
|
return evaluateExpressions((FlowFile) null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final AttributeValueDecorator decorator) throws ProcessException {
|
||||||
|
return evaluateExpressions((FlowFile) null, decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String evaluateExpressions(final FlowFile flowFile) throws ProcessException {
|
||||||
|
return evaluateExpressions(flowFile, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public abstract class BooleanEvaluator implements Evaluator<Boolean> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEvaluationsRemaining() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class BooleanQueryResult implements QueryResult<Boolean> {
|
||||||
|
|
||||||
|
private final Boolean value;
|
||||||
|
|
||||||
|
public BooleanQueryResult(final Boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public abstract class DateEvaluator implements Evaluator<Date> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEvaluationsRemaining() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class DateQueryResult implements QueryResult<Date> {
|
||||||
|
|
||||||
|
private final Date date;
|
||||||
|
|
||||||
|
public DateQueryResult(final Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getValue() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public interface Evaluator<T> {
|
||||||
|
|
||||||
|
QueryResult<T> evaluate(Map<String, String> attributes);
|
||||||
|
|
||||||
|
ResultType getResultType();
|
||||||
|
|
||||||
|
int getEvaluationsRemaining();
|
||||||
|
|
||||||
|
Evaluator<?> getSubjectEvaluator();
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public abstract class NumberEvaluator implements Evaluator<Long> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEvaluationsRemaining() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class NumberQueryResult implements QueryResult<Long> {
|
||||||
|
|
||||||
|
private final Long value;
|
||||||
|
|
||||||
|
public NumberQueryResult(final Long value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public interface QueryResult<T> {
|
||||||
|
|
||||||
|
T getValue();
|
||||||
|
|
||||||
|
ResultType getResultType();
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public abstract class StringEvaluator implements Evaluator<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEvaluationsRemaining() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation;
|
||||||
|
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class StringQueryResult implements QueryResult<String> {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public StringQueryResult(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultType getResultType() {
|
||||||
|
return ResultType.STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(getValue());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.cast;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class BooleanCastEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subjectEvaluator;
|
||||||
|
|
||||||
|
public BooleanCastEvaluator(final StringEvaluator subjectEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<String> result = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (result.getValue() == null) {
|
||||||
|
return new BooleanQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(Boolean.valueOf(result.getValue().trim()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.cast;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException;
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class DateCastEvaluator extends DateEvaluator {
|
||||||
|
|
||||||
|
public static final String DATE_TO_STRING_FORMAT = "EEE MMM dd HH:mm:ss zzz yyyy";
|
||||||
|
public static final Pattern DATE_TO_STRING_PATTERN = Pattern.compile("(?:[a-zA-Z]{3} ){2}\\d{2} \\d{2}\\:\\d{2}\\:\\d{2} (?:.*?) \\d{4}");
|
||||||
|
|
||||||
|
public static final String ALTERNATE_FORMAT_WITHOUT_MILLIS = "yyyy/MM/dd HH:mm:ss";
|
||||||
|
public static final String ALTERNATE_FORMAT_WITH_MILLIS = "yyyy/MM/dd HH:mm:ss.SSS";
|
||||||
|
public static final Pattern ALTERNATE_PATTERN = Pattern.compile("\\d{4}/\\d{2}/\\d{2} \\d{2}\\:\\d{2}\\:\\d{2}(\\.\\d{3})?");
|
||||||
|
|
||||||
|
public static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
|
||||||
|
|
||||||
|
private final Evaluator<?> subjectEvaluator;
|
||||||
|
|
||||||
|
public DateCastEvaluator(final Evaluator<?> subjectEvaluator) {
|
||||||
|
if (subjectEvaluator.getResultType() == ResultType.BOOLEAN) {
|
||||||
|
throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + subjectEvaluator.getResultType() + " to " + ResultType.DATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Date> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<?> result = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (result.getValue() == null) {
|
||||||
|
return new DateQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (result.getResultType()) {
|
||||||
|
case DATE:
|
||||||
|
return (DateQueryResult) result;
|
||||||
|
case STRING:
|
||||||
|
final String value = ((StringQueryResult) result).getValue().trim();
|
||||||
|
if (DATE_TO_STRING_PATTERN.matcher(value).matches()) {
|
||||||
|
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_TO_STRING_FORMAT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Date date = sdf.parse(value);
|
||||||
|
return new DateQueryResult(date);
|
||||||
|
} catch (final ParseException pe) {
|
||||||
|
throw new AttributeExpressionLanguageException("Could not parse input as date", pe);
|
||||||
|
}
|
||||||
|
} else if (NUMBER_PATTERN.matcher(value).matches()) {
|
||||||
|
return new DateQueryResult(new Date(Long.valueOf(value)));
|
||||||
|
} else {
|
||||||
|
final Matcher altMatcher = ALTERNATE_PATTERN.matcher(value);
|
||||||
|
if (altMatcher.matches()) {
|
||||||
|
final String millisValue = altMatcher.group(1);
|
||||||
|
|
||||||
|
final String format;
|
||||||
|
if (millisValue == null) {
|
||||||
|
format = ALTERNATE_FORMAT_WITHOUT_MILLIS;
|
||||||
|
} else {
|
||||||
|
format = ALTERNATE_FORMAT_WITH_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Date date = sdf.parse(value);
|
||||||
|
return new DateQueryResult(date);
|
||||||
|
} catch (final ParseException pe) {
|
||||||
|
throw new AttributeExpressionLanguageException("Could not parse input as date", pe);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new AttributeExpressionLanguageException("Could not implicitly convert input to DATE: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case NUMBER:
|
||||||
|
return new DateQueryResult(new Date((Long) result.getValue()));
|
||||||
|
default:
|
||||||
|
return new DateQueryResult(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.cast;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException;
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class NumberCastEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subjectEvaluator;
|
||||||
|
private static final Pattern NUMBER_PATTERN = Pattern.compile("-?\\d+");
|
||||||
|
|
||||||
|
public NumberCastEvaluator(final Evaluator<?> subjectEvaluator) {
|
||||||
|
if (subjectEvaluator.getResultType() == ResultType.BOOLEAN) {
|
||||||
|
throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + subjectEvaluator.getResultType() + " to " + ResultType.NUMBER);
|
||||||
|
}
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<?> result = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (result.getValue() == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (result.getResultType()) {
|
||||||
|
case NUMBER:
|
||||||
|
return (NumberQueryResult) result;
|
||||||
|
case STRING:
|
||||||
|
final String trimmed = ((StringQueryResult) result).getValue().trim();
|
||||||
|
if (NUMBER_PATTERN.matcher(trimmed).matches()) {
|
||||||
|
return new NumberQueryResult(Long.valueOf(trimmed));
|
||||||
|
} else {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
case DATE:
|
||||||
|
return new NumberQueryResult(((DateQueryResult) result).getValue().getTime());
|
||||||
|
default:
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.cast;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class StringCastEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subjectEvaluator;
|
||||||
|
|
||||||
|
public StringCastEvaluator(final Evaluator<?> subjectEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<?> result = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (result.getValue() == null) {
|
||||||
|
return new StringQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringQueryResult(String.valueOf(result.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class AndEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final BooleanEvaluator subjectEvaluator;
|
||||||
|
private final BooleanEvaluator rhsEvaluator;
|
||||||
|
|
||||||
|
public AndEvaluator(final BooleanEvaluator subjectEvaluator, final BooleanEvaluator rhsEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
this.rhsEvaluator = rhsEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<Boolean> subjectValue = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.FALSE.equals(subjectValue.getValue())) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final QueryResult<Boolean> rhsValue = rhsEvaluator.evaluate(attributes);
|
||||||
|
if (rhsValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(rhsValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class AppendEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator appendEvaluator;
|
||||||
|
|
||||||
|
public AppendEvaluator(final StringEvaluator subject, final StringEvaluator append) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.appendEvaluator = append;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
final String appendValue = appendEvaluator.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
final String result = (subjectValue == null ? "" : subjectValue)
|
||||||
|
+ (appendValue == null ? "" : appendValue);
|
||||||
|
return new StringQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class AttributeEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator nameEvaluator;
|
||||||
|
|
||||||
|
public AttributeEvaluator(final StringEvaluator nameEvaluator) {
|
||||||
|
this.nameEvaluator = nameEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String nameValue = nameEvaluator.evaluate(attributes).getValue();
|
||||||
|
final String attributeValue = attributes.get(nameValue);
|
||||||
|
return new StringQueryResult(attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class ContainsEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
|
||||||
|
public ContainsEvaluator(final StringEvaluator subject, final StringEvaluator search) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String searchString = search.evaluate(attributes).getValue();
|
||||||
|
return new BooleanQueryResult(searchString == null ? false : subjectValue.contains(searchString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class DateToNumberEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final DateEvaluator subjectEvaluator;
|
||||||
|
|
||||||
|
public DateToNumberEvaluator(final DateEvaluator subjectEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<Date> subjectResult = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (subjectResult.getValue() == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NumberQueryResult(subjectResult.getValue().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class DivideEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator divideValue;
|
||||||
|
|
||||||
|
public DivideEvaluator(final NumberEvaluator subject, final NumberEvaluator divideValue) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.divideValue = divideValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long divide = divideValue.evaluate(attributes).getValue();
|
||||||
|
if (divide == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long result = subjectValue / divide;
|
||||||
|
return new NumberQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class EndsWithEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
|
||||||
|
public EndsWithEvaluator(final StringEvaluator subject, final StringEvaluator search) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String searchString = search.evaluate(attributes).getValue();
|
||||||
|
return new BooleanQueryResult(searchString == null ? false : subjectValue.endsWith(searchString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.expression.AttributeExpression.ResultType;
|
||||||
|
|
||||||
|
public class EqualsEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subject;
|
||||||
|
private final Evaluator<?> compareTo;
|
||||||
|
|
||||||
|
public EqualsEvaluator(final Evaluator<?> subject, final Evaluator<?> compareTo) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.compareTo = compareTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Object a = subject.evaluate(attributes).getValue();
|
||||||
|
if (a == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object b = compareTo.evaluate(attributes).getValue();
|
||||||
|
if (b == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subject.getResultType() == compareTo.getResultType()) {
|
||||||
|
return new BooleanQueryResult(a.equals(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
final String normalizedSubjectValue = normalizeValue(subject.getResultType(), a);
|
||||||
|
if (normalizedSubjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String normalizedCompareToValue = normalizeValue(compareTo.getResultType(), b);
|
||||||
|
if (normalizedCompareToValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(normalizedSubjectValue.equals(normalizedCompareToValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeValue(final ResultType type, final Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case STRING:
|
||||||
|
return (String) value;
|
||||||
|
case DATE:
|
||||||
|
return String.valueOf(((Date) value).getTime());
|
||||||
|
case BOOLEAN:
|
||||||
|
case NUMBER:
|
||||||
|
default:
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class EqualsIgnoreCaseEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subject;
|
||||||
|
private final Evaluator<?> compareTo;
|
||||||
|
|
||||||
|
public EqualsIgnoreCaseEvaluator(final Evaluator<?> subject, final Evaluator<?> compareTo) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.compareTo = compareTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Object a = subject.evaluate(attributes).getValue();
|
||||||
|
if (a == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object b = compareTo.evaluate(attributes).getValue();
|
||||||
|
if (b == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a instanceof String && b instanceof String) {
|
||||||
|
return new BooleanQueryResult(((String) a).equalsIgnoreCase((String) b));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(a.equals(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.literals.StringLiteralEvaluator;
|
||||||
|
|
||||||
|
public class FindEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
|
||||||
|
private final Pattern compiledPattern;
|
||||||
|
|
||||||
|
public FindEvaluator(final StringEvaluator subject, final StringEvaluator search) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
|
||||||
|
// if the search string is a literal, we don't need to evaluate it each time; we can just
|
||||||
|
// pre-compile it. Otherwise, it must be compiled every time.
|
||||||
|
if (search instanceof StringLiteralEvaluator) {
|
||||||
|
this.compiledPattern = Pattern.compile(search.evaluate(null).getValue());
|
||||||
|
} else {
|
||||||
|
this.compiledPattern = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
final Pattern pattern;
|
||||||
|
if (compiledPattern == null) {
|
||||||
|
pattern = Pattern.compile(search.evaluate(attributes).getValue());
|
||||||
|
} else {
|
||||||
|
pattern = compiledPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean found = pattern.matcher(subjectValue).find();
|
||||||
|
|
||||||
|
return new BooleanQueryResult(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class FormatEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final DateEvaluator subject;
|
||||||
|
private final StringEvaluator format;
|
||||||
|
|
||||||
|
public FormatEvaluator(final DateEvaluator subject, final StringEvaluator format) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Date subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new StringQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final QueryResult<String> formatResult = format.evaluate(attributes);
|
||||||
|
final String format = formatResult.getValue();
|
||||||
|
if (format == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringQueryResult(new SimpleDateFormat(format).format(subjectValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class GreaterThanEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator comparison;
|
||||||
|
|
||||||
|
public GreaterThanEvaluator(final NumberEvaluator subject, final NumberEvaluator comparison) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.comparison = comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long comparisonValue = comparison.evaluate(attributes).getValue();
|
||||||
|
if (comparisonValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(subjectValue > comparisonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class GreaterThanOrEqualEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator comparison;
|
||||||
|
|
||||||
|
public GreaterThanOrEqualEvaluator(final NumberEvaluator subject, final NumberEvaluator comparison) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.comparison = comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long comparisonValue = comparison.evaluate(attributes).getValue();
|
||||||
|
if (comparisonValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(subjectValue >= comparisonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class HostnameEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringQueryResult hostname;
|
||||||
|
|
||||||
|
public HostnameEvaluator(final boolean preferFQDN) throws UnknownHostException {
|
||||||
|
String address;
|
||||||
|
|
||||||
|
if (preferFQDN) {
|
||||||
|
try {
|
||||||
|
address = InetAddress.getLocalHost().getCanonicalHostName();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
address = InetAddress.getLocalHost().getHostName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
address = InetAddress.getLocalHost().getHostName();
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname = new StringQueryResult(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class IPEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringQueryResult ipAddress;
|
||||||
|
|
||||||
|
public IPEvaluator() throws UnknownHostException {
|
||||||
|
ipAddress = new StringQueryResult(InetAddress.getLocalHost().getHostAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
return ipAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class IndexOfEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator indexEvaluator;
|
||||||
|
|
||||||
|
public IndexOfEvaluator(final StringEvaluator subject, final StringEvaluator indexEvaluator) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.indexEvaluator = indexEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(-1L);
|
||||||
|
}
|
||||||
|
final String indexEvalValue = indexEvaluator.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
return new NumberQueryResult((long) subjectValue.indexOf(indexEvalValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class IsNullEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subject;
|
||||||
|
|
||||||
|
public IsNullEvaluator(final Evaluator<?> subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Object subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
return new BooleanQueryResult(subjectValue == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class LastIndexOfEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator indexEvaluator;
|
||||||
|
|
||||||
|
public LastIndexOfEvaluator(final StringEvaluator subject, final StringEvaluator indexEvaluator) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.indexEvaluator = indexEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(-1L);
|
||||||
|
}
|
||||||
|
final String indexEvalValue = indexEvaluator.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
return new NumberQueryResult((long) subjectValue.lastIndexOf(indexEvalValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class LengthEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
|
||||||
|
public LengthEvaluator(final StringEvaluator subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
return new NumberQueryResult((long) ((subjectValue == null) ? 0 : subjectValue.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class LessThanEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator comparison;
|
||||||
|
|
||||||
|
public LessThanEvaluator(final NumberEvaluator subject, final NumberEvaluator comparison) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.comparison = comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long comparisonValue = comparison.evaluate(attributes).getValue();
|
||||||
|
if (comparisonValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(subjectValue < comparisonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class LessThanOrEqualEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator comparison;
|
||||||
|
|
||||||
|
public LessThanOrEqualEvaluator(final NumberEvaluator subject, final NumberEvaluator comparison) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.comparison = comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long comparisonValue = comparison.evaluate(attributes).getValue();
|
||||||
|
if (comparisonValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(subjectValue <= comparisonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.literals.StringLiteralEvaluator;
|
||||||
|
|
||||||
|
public class MatchesEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
|
||||||
|
private final Pattern compiledPattern;
|
||||||
|
|
||||||
|
public MatchesEvaluator(final StringEvaluator subject, final StringEvaluator search) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
|
||||||
|
// if the search string is a literal, we don't need to evaluate it each time; we can just
|
||||||
|
// pre-compile it. Otherwise, it must be compiled every time.
|
||||||
|
if (search instanceof StringLiteralEvaluator) {
|
||||||
|
this.compiledPattern = Pattern.compile(search.evaluate(null).getValue());
|
||||||
|
} else {
|
||||||
|
this.compiledPattern = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
final Pattern pattern;
|
||||||
|
if (compiledPattern == null) {
|
||||||
|
pattern = Pattern.compile(search.evaluate(attributes).getValue());
|
||||||
|
} else {
|
||||||
|
pattern = compiledPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean matches = pattern.matcher(subjectValue).matches();
|
||||||
|
return new BooleanQueryResult(matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class MinusEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator minusValue;
|
||||||
|
|
||||||
|
public MinusEvaluator(final NumberEvaluator subject, final NumberEvaluator minusValue) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.minusValue = minusValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long minus = minusValue.evaluate(attributes).getValue();
|
||||||
|
if (minus == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long result = subjectValue - minus;
|
||||||
|
return new NumberQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class ModEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator modValue;
|
||||||
|
|
||||||
|
public ModEvaluator(final NumberEvaluator subject, final NumberEvaluator modValue) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.modValue = modValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long mod = modValue.evaluate(attributes).getValue();
|
||||||
|
if (mod == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long result = subjectValue % mod;
|
||||||
|
return new NumberQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class MultiplyEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator multiplyValue;
|
||||||
|
|
||||||
|
public MultiplyEvaluator(final NumberEvaluator subject, final NumberEvaluator multiplyValue) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.multiplyValue = multiplyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long multiply = multiplyValue.evaluate(attributes).getValue();
|
||||||
|
if (multiply == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long result = subjectValue * multiply;
|
||||||
|
return new NumberQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class NotEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final BooleanEvaluator subjectEvaluator;
|
||||||
|
|
||||||
|
public NotEvaluator(final BooleanEvaluator subjectEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<Boolean> subjectValue = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(!subjectValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class NotNullEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final Evaluator<?> subject;
|
||||||
|
|
||||||
|
public NotNullEvaluator(final Evaluator<?> subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Object subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
return new BooleanQueryResult(subjectValue != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class NowEvaluator extends DateEvaluator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Date> evaluate(final Map<String, String> attributes) {
|
||||||
|
return new DateQueryResult(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class NumberToDateEvaluator extends DateEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
|
||||||
|
public NumberToDateEvaluator(final NumberEvaluator subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Date> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<Long> result = subject.evaluate(attributes);
|
||||||
|
final Long value = result.getValue();
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DateQueryResult(new Date(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class OneUpSequenceEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private static final AtomicLong value = new AtomicLong(0L);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
return new NumberQueryResult(value.getAndIncrement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class OrEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final BooleanEvaluator subjectEvaluator;
|
||||||
|
private final BooleanEvaluator rhsEvaluator;
|
||||||
|
|
||||||
|
public OrEvaluator(final BooleanEvaluator subjectEvaluator, final BooleanEvaluator rhsEvaluator) {
|
||||||
|
this.subjectEvaluator = subjectEvaluator;
|
||||||
|
this.rhsEvaluator = rhsEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final QueryResult<Boolean> subjectValue = subjectEvaluator.evaluate(attributes);
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(subjectValue.getValue())) {
|
||||||
|
return new BooleanQueryResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
final QueryResult<Boolean> rhsValue = rhsEvaluator.evaluate(attributes);
|
||||||
|
if (rhsValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BooleanQueryResult(rhsValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subjectEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
|
||||||
|
public class PlusEvaluator extends NumberEvaluator {
|
||||||
|
|
||||||
|
private final NumberEvaluator subject;
|
||||||
|
private final NumberEvaluator plusValue;
|
||||||
|
|
||||||
|
public PlusEvaluator(final NumberEvaluator subject, final NumberEvaluator plusValue) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.plusValue = plusValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Long> evaluate(final Map<String, String> attributes) {
|
||||||
|
final Long subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long plus = plusValue.evaluate(attributes).getValue();
|
||||||
|
if (plus == null) {
|
||||||
|
return new NumberQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final long result = subjectValue + plus;
|
||||||
|
return new NumberQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class PrependEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator prependEvaluator;
|
||||||
|
|
||||||
|
public PrependEvaluator(final StringEvaluator subject, final StringEvaluator prepend) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.prependEvaluator = prepend;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
final String prependValue = prependEvaluator.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
final String result = (prependValue == null ? "" : prependValue) + (subjectValue == null ? "" : subjectValue);
|
||||||
|
return new StringQueryResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class ReplaceAllEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
private final StringEvaluator replacement;
|
||||||
|
|
||||||
|
public ReplaceAllEvaluator(final StringEvaluator subject, final StringEvaluator search, final StringEvaluator replacement) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
this.replacement = replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new StringQueryResult(null);
|
||||||
|
}
|
||||||
|
final String searchValue = search.evaluate(attributes).getValue();
|
||||||
|
final String replacementValue = replacement.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
return new StringQueryResult(subjectValue.replaceAll(searchValue, replacementValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class ReplaceEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
private final StringEvaluator replacement;
|
||||||
|
|
||||||
|
public ReplaceEvaluator(final StringEvaluator subject, final StringEvaluator search, final StringEvaluator replacement) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
this.replacement = replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new StringQueryResult(null);
|
||||||
|
}
|
||||||
|
final String searchValue = search.evaluate(attributes).getValue();
|
||||||
|
final String replacementValue = replacement.evaluate(attributes).getValue();
|
||||||
|
|
||||||
|
return new StringQueryResult(subjectValue.replace(searchValue, replacementValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult;
|
||||||
|
|
||||||
|
public class ReplaceNullEvaluator extends StringEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator resultEvaluator;
|
||||||
|
|
||||||
|
public ReplaceNullEvaluator(final StringEvaluator subject, final StringEvaluator resultEvaluator) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.resultEvaluator = resultEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<String> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
return new StringQueryResult(subjectValue == null ? resultEvaluator.evaluate(attributes).getValue() : subjectValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
|
||||||
|
public class StartsWithEvaluator extends BooleanEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator search;
|
||||||
|
|
||||||
|
public StartsWithEvaluator(final StringEvaluator subject, final StringEvaluator search) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.search = search;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Boolean> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null) {
|
||||||
|
return new BooleanQueryResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String searchString = search.evaluate(attributes).getValue();
|
||||||
|
return new BooleanQueryResult(searchString == null ? false : subjectValue.startsWith(searchString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.attribute.expression.language.evaluation.functions;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.Evaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.QueryResult;
|
||||||
|
import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator;
|
||||||
|
import org.apache.nifi.attribute.expression.language.exception.IllegalAttributeException;
|
||||||
|
|
||||||
|
public class StringToDateEvaluator extends DateEvaluator {
|
||||||
|
|
||||||
|
private final StringEvaluator subject;
|
||||||
|
private final StringEvaluator format;
|
||||||
|
|
||||||
|
public StringToDateEvaluator(final StringEvaluator subject, final StringEvaluator format) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryResult<Date> evaluate(final Map<String, String> attributes) {
|
||||||
|
final String subjectValue = subject.evaluate(attributes).getValue();
|
||||||
|
final String formatValue = format.evaluate(attributes).getValue();
|
||||||
|
if (subjectValue == null || formatValue == null) {
|
||||||
|
return new DateQueryResult(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new DateQueryResult(new SimpleDateFormat(formatValue).parse(subjectValue));
|
||||||
|
} catch (final ParseException e) {
|
||||||
|
throw new IllegalAttributeException("Cannot parse attribute value as a date; date format: "
|
||||||
|
+ formatValue + "; attribute value: " + subjectValue);
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
throw new IllegalAttributeException("Invalid date format: " + formatValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Evaluator<?> getSubjectEvaluator() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue