This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch support/nifi-1.x
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/support/nifi-1.x by this push:
new 6037af86e8 NIFI-10955 Added optional preprocessing to JASN1Reader
6037af86e8 is described below
commit 6037af86e898aeec8e9a922d4abe82d655af259e
Author: Tamas Palfy <[email protected]>
AuthorDate: Tue Dec 6 19:27:49 2022 +0100
NIFI-10955 Added optional preprocessing to JASN1Reader
This close #6769
Signed-off-by: David Handermann <[email protected]>
---
.../nifi-asn1-bundle/nifi-asn1-services/pom.xml | 8 +
.../java/org/apache/nifi/jasn1/JASN1Reader.java | 95 ++++++++----
.../nifi/jasn1/preprocess/AsnPreprocessor.java | 23 +++
.../jasn1/preprocess/AsnPreprocessorEngine.java | 105 +++++++++++++
.../preprocessors/ConstraintAsnPreprocessor.java | 91 +++++++++++
.../HuggingCommentAsnPreprocessor.java | 49 ++++++
.../VersionBracketAsnPreprocessor.java | 89 +++++++++++
.../additionalDetails.html | 57 +++++++
.../preprocess/AsnPreprocessorEngineTest.java | 167 +++++++++++++++++++++
.../preprocessors/AbstractAsnPreprocessorTest.java | 49 ++++++
.../ConstraintAsnPreprocessorTest.java | 32 ++++
.../HuggingCommentAsnPreprocessorTest.java | 32 ++++
.../VersionBracketAsnPreprocessorTest.java | 32 ++++
...preprocessed_test_complex_for_preprocessing.asn | 15 ++
.../resources/preprocessed_test_constraints.asn | 27 ++++
.../preprocessed_test_hugging_comment.asn | 12 ++
.../preprocessed_test_version_bracket.asn | 44 ++++++
.../resources/test_complex_for_preprocessing.asn | 15 ++
.../src/test/resources/test_constraints.asn | 27 ++++
.../src/test/resources/test_hugging_comment.asn | 12 ++
.../src/test/resources/test_version_bracket.asn | 44 ++++++
21 files changed, 997 insertions(+), 28 deletions(-)
diff --git a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/pom.xml
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/pom.xml
index 763286de75..e9844c6227 100644
--- a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/pom.xml
+++ b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/pom.xml
@@ -141,6 +141,14 @@
<exclude>src/test/resources/examples/basic-types.dat</exclude>
<exclude>src/test/resources/examples/composite.dat</exclude>
<exclude>src/test/resources/examples/tbcd-string.dat</exclude>
+
<exclude>src/test/resources/test_hugging_comment.asn</exclude>
+
<exclude>src/test/resources/test_version_bracket.asn</exclude>
+
<exclude>src/test/resources/test_constraints.asn</exclude>
+
<exclude>src/test/resources/test_complex_for_preprocessing.asn</exclude>
+
<exclude>src/test/resources/preprocessed_test_hugging_comment.asn</exclude>
+
<exclude>src/test/resources/preprocessed_test_version_bracket.asn</exclude>
+
<exclude>src/test/resources/preprocessed_test_constraints.asn</exclude>
+
<exclude>src/test/resources/preprocessed_test_complex_for_preprocessing.asn</exclude>
</excludes>
</configuration>
</plugin>
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/JASN1Reader.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/JASN1Reader.java
index c2bbd99761..ba40f45b78 100644
---
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/JASN1Reader.java
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/JASN1Reader.java
@@ -29,6 +29,7 @@ import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnDisabled;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
import org.apache.nifi.components.AbstractConfigurableComponent;
+import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.components.ValidationContext;
@@ -36,12 +37,10 @@ import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.controller.ControllerServiceInitializationContext;
import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.jasn1.preprocess.AsnPreprocessorEngine;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
-import org.apache.nifi.reporting.InitializationException;
-import org.apache.nifi.schema.access.SchemaNotFoundException;
-import org.apache.nifi.serialization.MalformedRecordException;
import org.apache.nifi.serialization.RecordReader;
import org.apache.nifi.serialization.RecordReaderFactory;
import org.apache.nifi.util.file.classloader.ClassLoaderUtils;
@@ -134,16 +133,51 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
.required(false)
.build();
+ private static final AllowableValue DEFAULT = new AllowableValue(
+ "DEFAULT",
+ "Default",
+ "No additional preprocessing should occur, use original schema."
+ );
+
+ private static final AllowableValue ADDITIONAL_PREPROCESSING = new
AllowableValue(
+ "ADDITIONAL_PREPROCESSING",
+ "Additional Preprocessing",
+ "Perform additional preprocessing, resulting in potentially
modified schema. (See additional details for more information.)"
+ );
+
+ private static final PropertyDescriptor SCHEMA_PREPARATION_STRATEGY = new
PropertyDescriptor.Builder()
+ .name("Schema Preparation Strategy")
+ .description("When set, NiFi will do additional preprocessing steps
that creates modified versions of the provided ASN files," +
+ " removing unsupported features in a way that makes them less
strict but otherwise should still be compatible with incoming data." +
+ " The original files will remain intact and new ones will be
created with the same names in the directory defined in the 'Additional
Preprocessing Output Directory' property." +
+ " For more information about these additional preprocessing
steps please see Additional Details - Additional Preprocessing.")
+ .allowableValues(DEFAULT, ADDITIONAL_PREPROCESSING)
+ .required(true)
+ .defaultValue(DEFAULT.getValue())
+ .build();
+
+ private static final PropertyDescriptor SCHEMA_PREPARATION_DIRECTORY = new
PropertyDescriptor.Builder()
+ .name("Schema Preparation Directory")
+ .description("When the processor is configured to do additional
preprocessing, new modified schema files will be created in this directory." +
+ " For more information about additional preprocessing please
see description of the 'Do Additional Preprocessing' property or Additional
Details - Additional Preprocessing.")
+ .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
+ .addValidator(StandardValidators.createDirectoryExistsValidator(true,
false))
+ .dependsOn(SCHEMA_PREPARATION_STRATEGY, ADDITIONAL_PREPROCESSING)
+ .required(true)
+ .build();
+
private final List<PropertyDescriptor> propertyDescriptors = Arrays.asList(
ROOT_MODEL_NAME,
ROOT_CLASS_NAME,
- ASN_FILES
+ ASN_FILES,
+ SCHEMA_PREPARATION_STRATEGY,
+ SCHEMA_PREPARATION_DIRECTORY
);
private String identifier;
ComponentLog logger;
- private RecordSchemaProvider schemaProvider = new RecordSchemaProvider();
+ private final RecordSchemaProvider schemaProvider = new
RecordSchemaProvider();
volatile Path asnOutDir;
private volatile PropertyValue rootModelNameProperty;
@@ -159,7 +193,7 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
}
@Override
- public void initialize(ControllerServiceInitializationContext context)
throws InitializationException {
+ public void initialize(ControllerServiceInitializationContext context) {
identifier = context.getIdentifier();
logger = context.getLogger();
}
@@ -175,7 +209,7 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
results.add(new ValidationResult.Builder()
.subject(ROOT_MODEL_NAME.getName())
.valid(false)
- .explanation("Onle one of '" +
ROOT_MODEL_NAME.getDisplayName() + "' or '" + ROOT_CLASS_NAME.getDisplayName()
+ "' should be set!")
+ .explanation("Only one of '" +
ROOT_MODEL_NAME.getDisplayName() + "' or '" + ROOT_CLASS_NAME.getDisplayName()
+ "' should be set!")
.build());
}
@@ -191,12 +225,25 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
}
@OnEnabled
- public void onEnabled(final ConfigurationContext context) throws
InitializationException {
+ public void onEnabled(final ConfigurationContext context) {
if (context.getProperty(ASN_FILES) != null &&
context.getProperty(ASN_FILES).isSet()) {
- String[] asnFilesPaths =
Arrays.stream(context.getProperty(ASN_FILES).evaluateAttributeExpressions().getValue().split(","))
- .map(String::trim)
- .toArray(String[]::new);
+ String asnFilesString =
context.getProperty(ASN_FILES).evaluateAttributeExpressions().getValue();
+
+ if
(ADDITIONAL_PREPROCESSING.getValue().equals(context.getProperty(SCHEMA_PREPARATION_STRATEGY).getValue()))
{
+ final AsnPreprocessorEngine asnPreprocessorEngine = new
AsnPreprocessorEngine();
+
+ final String preprocessOutputDirectory =
context.getProperty(SCHEMA_PREPARATION_DIRECTORY).evaluateAttributeExpressions().getValue();
+ asnFilesString = asnPreprocessorEngine.preprocess(
+ logger,
+ asnFilesString,
+ preprocessOutputDirectory
+ );
+ }
+
+ final String[] asnFilesPaths =
Arrays.stream(asnFilesString.split(","))
+ .map(String::trim)
+ .toArray(String[]::new);
compileAsnToClass(asnFilesPaths);
}
@@ -211,7 +258,7 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
customClassLoader = this.getClass().getClassLoader();
}
} catch (final Exception ex) {
- logger.error("Couldn't create classloader for compiled classes.",
ex);
+ logger.error("Could not create ClassLoader for compiled ASN.1
classes", ex);
}
rootModelNameProperty = context.getProperty(ROOT_MODEL_NAME);
@@ -223,18 +270,10 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
private void compileAsnToClass(String... asnFilePaths) {
try {
asnOutDir = Files.createTempDirectory(getIdentifier() + "_asn_");
-
- logger.info("ASN files will be compiled to '" + asnOutDir + "'");
} catch (IOException e) {
- throw new ProcessException("Couldn't create temporary directory
for compiled asn files.", e);
+ throw new ProcessException("Could not create temporary directory
for compiled ASN.1 files", e);
}
- List<String> asnCompilerArguments = new ArrayList<>();
- asnCompilerArguments.add("-f");
- asnCompilerArguments.addAll(Arrays.asList(asnFilePaths));
- asnCompilerArguments.add("-o");
- asnCompilerArguments.add(asnOutDir.toString());
-
HashMap<String, AsnModule> modulesByName = new HashMap<>();
Exception parseException = null;
@@ -295,12 +334,12 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
Boolean success = task.call();
if (!success) {
- Set<String> errorMessages = new LinkedHashSet();
+ Set<String> errorMessages = new LinkedHashSet<>();
diagnosticListener.getDiagnostics().stream().map(d ->
d.getMessage(Locale.getDefault())).forEach(errorMessages::add);
errorMessages.forEach(logger::error);
- throw new ProcessException("Java compilation failed");
+ throw new ProcessException("ASN.1 Java compilation failed");
}
}
@@ -333,7 +372,7 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
InputStream in,
long inputLength,
ComponentLog logger
- ) throws MalformedRecordException, IOException, SchemaNotFoundException {
+ ) {
final String rootClassName;
if (rootModelNameProperty != null && rootModelNameProperty.isSet()) {
rootClassName =
guessRootClassName(rootModelNameProperty.evaluateAttributeExpressions(variables).getValue());
@@ -366,13 +405,13 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
}
};
+ AsnModel model = new AsnModel();
+ parser.module_definitions(model);
+
if (parseError.get()) {
throw new ProcessException("ASN.1 parsing failed");
}
- AsnModel model = new AsnModel();
- parser.module_definitions(model);
-
return model;
}
@@ -390,7 +429,7 @@ public class JASN1Reader extends
AbstractConfigurableComponent implements Record
return rootClassNameBuilder.toString();
} catch (Exception e) {
- throw new ProcessException("Couldn't infer root model name from '"
+ rootModelName + "'", e);
+ throw new ProcessException("Could not infer root model name from
'" + rootModelName + "'", e);
}
}
}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessor.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessor.java
new file mode 100644
index 0000000000..d58a5b4f02
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessor.java
@@ -0,0 +1,23 @@
+/*
+ * 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.jasn1.preprocess;
+
+import java.util.List;
+
+public interface AsnPreprocessor {
+ List<String> preprocessAsn(List<String> lines);
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngine.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngine.java
new file mode 100644
index 0000000000..7a3d82e465
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngine.java
@@ -0,0 +1,105 @@
+/*
+ * 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.jasn1.preprocess;
+
+import
org.apache.nifi.jasn1.preprocess.preprocessors.ConstraintAsnPreprocessor;
+import
org.apache.nifi.jasn1.preprocess.preprocessors.HuggingCommentAsnPreprocessor;
+import
org.apache.nifi.jasn1.preprocess.preprocessors.VersionBracketAsnPreprocessor;
+import org.apache.nifi.logging.ComponentLog;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+public class AsnPreprocessorEngine {
+ public static final String COMMA = "\\s*,\\s*";
+
+ private static final List<AsnPreprocessor> PREPROCESSORS = Arrays.asList(
+ new HuggingCommentAsnPreprocessor(),
+ new VersionBracketAsnPreprocessor(),
+ new ConstraintAsnPreprocessor()
+ );
+
+ public String preprocess(
+ ComponentLog componentLog,
+ String asnFilesString,
+ String outputDirectory
+ ) {
+ final String[] inputFiles = asnFilesString.split(COMMA);
+
+ final StringJoiner preprocessedInputFiles = new StringJoiner(",");
+
+ for (String inputFile : inputFiles) {
+ final Path inputFilePath = Paths.get(inputFile);
+ final Path fileName = inputFilePath.getFileName();
+
+ final List<String> lines = readAsnLines(componentLog, inputFile,
inputFilePath);
+
+ final List<String> preprocessedLines = preprocessAsn(lines);
+
+ final String preprocessedAsn = preprocessedLines
+ .stream()
+ .collect(Collectors.joining(System.lineSeparator()));
+
+ final Path preprocessedAsnPath = Paths.get(outputDirectory,
fileName.toString());
+ preprocessedInputFiles.add(preprocessedAsnPath.toString());
+
+ writePreprocessedAsn(componentLog, preprocessedAsn,
preprocessedAsnPath);
+ }
+
+ return preprocessedInputFiles.toString();
+ }
+
+ List<String> preprocessAsn(List<String> lines) {
+ List<String> preprocessedAsn = lines;
+
+ for (AsnPreprocessor preprocessor : getPreprocessors()) {
+ preprocessedAsn = preprocessor.preprocessAsn(preprocessedAsn);
+ }
+
+ return preprocessedAsn;
+ }
+
+ List<String> readAsnLines(ComponentLog componentLog, String inputFile,
Path inputFilePath) {
+ List<String> lines;
+ try {
+ lines = Files.readAllLines(inputFilePath);
+ } catch (IOException e) {
+ throw new UncheckedIOException(String.format("Read ASN.1 Schema
failed [%s]", inputFile), e);
+ }
+ return lines;
+ }
+
+ void writePreprocessedAsn(ComponentLog componentLog, String
preprocessedAsn, Path preprocessedAsnPath) {
+ try {
+ Files.write(preprocessedAsnPath,
preprocessedAsn.getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new UncheckedIOException(String.format("Write ASN.1 Schema
failed [%s]", preprocessedAsnPath), e);
+ }
+ }
+
+ List<AsnPreprocessor> getPreprocessors() {
+ return PREPROCESSORS;
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessor.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessor.java
new file mode 100644
index 0000000000..1d3fd8eb5c
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessor.java
@@ -0,0 +1,91 @@
+/*
+ * 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.jasn1.preprocess.preprocessors;
+
+import org.apache.nifi.jasn1.preprocess.AsnPreprocessor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ConstraintAsnPreprocessor implements AsnPreprocessor {
+ public static final String OPEN_BRACKET = "(";
+ public static final String CLOSE_BRACKET = ")";
+
+ public static final Pattern ALLOWED = Pattern.compile("^(\\d+\\))(.*)");
+
+ @Override
+ public List<String> preprocessAsn(List<String> lines) {
+ final List<String> preprocessedLines = new ArrayList<>();
+
+ final AtomicInteger unclosedCounter = new AtomicInteger(0);
+ lines.forEach(line -> {
+ final StringBuilder preprocessedLine = new StringBuilder();
+
+ String contentToProcess = line;
+
+ while (contentToProcess.contains(OPEN_BRACKET) ||
contentToProcess.contains(CLOSE_BRACKET)) {
+ if (contentToProcess.matches("^\\s*--.*$")) {
+ break;
+ }
+
+ final int openBracketIndex =
contentToProcess.indexOf(OPEN_BRACKET);
+ final int closeBracketIndex =
contentToProcess.indexOf(CLOSE_BRACKET);
+
+ if (openBracketIndex != -1 && (openBracketIndex <
closeBracketIndex) || closeBracketIndex == -1) {
+ final String contentBeforeOpenBracket =
contentToProcess.substring(0, openBracketIndex);
+ final String contentAfterOpenBracket =
contentToProcess.substring(openBracketIndex + 1);
+
+ if (unclosedCounter.get() < 1) {
+ if (!contentBeforeOpenBracket.isEmpty()) {
+ preprocessedLine.append(contentBeforeOpenBracket +
" ");
+ // Adding a space " " because (...) blocks can
serve as separators so removing them might
+ // join together parts that should stay separated
+ }
+
+ final Matcher supportedMatcher =
ALLOWED.matcher(contentAfterOpenBracket);
+ if (supportedMatcher.matches()) {
+ preprocessedLine.append(OPEN_BRACKET +
supportedMatcher.group(1));
+ contentToProcess = supportedMatcher.group(2);
+ continue;
+ }
+ }
+
+ unclosedCounter.incrementAndGet();
+
+ contentToProcess = contentAfterOpenBracket;
+ } else if (closeBracketIndex != -1) {
+ unclosedCounter.decrementAndGet();
+
+ contentToProcess =
contentToProcess.substring(closeBracketIndex + 1);
+ }
+ }
+
+ if (unclosedCounter.get() < 1) {
+ if (!contentToProcess.isEmpty()) {
+ preprocessedLine.append(contentToProcess);
+ }
+ }
+
+ preprocessedLines.add(preprocessedLine.toString());
+ });
+
+ return preprocessedLines;
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessor.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessor.java
new file mode 100644
index 0000000000..8667f46e30
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessor.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.apache.nifi.jasn1.preprocess.AsnPreprocessor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HuggingCommentAsnPreprocessor implements AsnPreprocessor {
+ public static final Pattern HUGGING_COMMENT_PATTERN =
Pattern.compile("^(.*[^\\s])(--.*)$");
+
+ @Override
+ public List<String> preprocessAsn(List<String> lines) {
+ final List<String> preprocessedLines = new ArrayList<>();
+
+ lines.forEach(line -> {
+ final StringBuilder preprocessedLine = new StringBuilder();
+
+ final Matcher huggingCommentMather =
HUGGING_COMMENT_PATTERN.matcher(line);
+ if (huggingCommentMather.matches()) {
+ preprocessedLine.append(huggingCommentMather.group(1))
+ .append(" ")
+ .append(huggingCommentMather.group(2));
+ preprocessedLines.add(preprocessedLine.toString());
+ } else {
+ preprocessedLines.add(line);
+ }
+ });
+
+ return preprocessedLines;
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessor.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessor.java
new file mode 100644
index 0000000000..ca976de535
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessor.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.apache.nifi.jasn1.preprocess.AsnPreprocessor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Pattern;
+
+public class VersionBracketAsnPreprocessor implements AsnPreprocessor {
+ public static final String OPEN_VERSION_BRACKET = "[[";
+ public static final String CLOSE_VERSION_BRACKET = "]]";
+
+ public static final Pattern ONLY_WHITESPACES = Pattern.compile("^\\s*$");
+ public static final Pattern ONLY_COMMENT = Pattern.compile("^\\s*--.*$");
+ public static final Pattern IS_OPTIONAL_ALREADY =
Pattern.compile(".*OPTIONAL\\s*,?\\s*$");
+
+ public static final String TRAILING_COMMA_WITH_POTENTIAL_WHITESPACES =
"(\\s*)(,?)(\\s*)$";
+ public static final String ADD_OPTIONAL = " OPTIONAL$1$2$3";
+
+ @Override
+ public List<String> preprocessAsn(List<String> lines) {
+ final List<String> preprocessedLines = new ArrayList<>();
+
+ final AtomicBoolean inVersionBracket = new AtomicBoolean(false);
+ lines.forEach(line -> {
+ final StringBuilder preprocessedLine = new StringBuilder();
+ String contentToProcess = line;
+
+ final int versionBracketStart =
contentToProcess.indexOf(OPEN_VERSION_BRACKET);
+ if (versionBracketStart > -1) {
+ inVersionBracket.set(true);
+
+ final String contentBeforeVersionBracket = line.substring(0,
versionBracketStart);
+ if (!contentBeforeVersionBracket.isEmpty()) {
+ preprocessedLine.append(contentBeforeVersionBracket);
+ }
+
+ contentToProcess =
contentToProcess.substring(versionBracketStart + 2);
+ }
+
+ final int versionBracketEnd =
contentToProcess.indexOf(CLOSE_VERSION_BRACKET);
+ String contentAfterVersionBracket = null;
+ if (versionBracketEnd > -1) {
+ contentAfterVersionBracket =
contentToProcess.substring(versionBracketEnd + 2);
+ contentToProcess = contentToProcess.substring(0,
versionBracketEnd);
+ }
+
+ if (inVersionBracket.get()
+ && !ONLY_WHITESPACES.matcher(contentToProcess).matches()
+ && !ONLY_COMMENT.matcher(contentToProcess).matches()
+ && !IS_OPTIONAL_ALREADY.matcher(contentToProcess).matches()
+ ) {
+ contentToProcess =
contentToProcess.replaceFirst(TRAILING_COMMA_WITH_POTENTIAL_WHITESPACES,
ADD_OPTIONAL);
+ }
+
+ if (!contentToProcess.isEmpty()) {
+ preprocessedLine.append(contentToProcess);
+ }
+
+ if (contentAfterVersionBracket != null) {
+ if (!contentAfterVersionBracket.isEmpty()) {
+ preprocessedLine.append(contentAfterVersionBracket);
+ }
+ inVersionBracket.set(false);
+ }
+
+ preprocessedLines.add(preprocessedLine.toString());
+ });
+
+ return preprocessedLines;
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/resources/docs/org.apache.nifi.jasn1.JASN1Reader/additionalDetails.html
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/resources/docs/org.apache.nifi.jasn1.JASN1Reader/additionalDetails.html
index 31edf6d64e..51ca11fdd9 100644
---
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/resources/docs/org.apache.nifi.jasn1.JASN1Reader/additionalDetails.html
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/main/resources/docs/org.apache.nifi.jasn1.JASN1Reader/additionalDetails.html
@@ -122,5 +122,62 @@
</li>
</ol>
</p>
+
+ <h3>Additional Preprocessing</h3>
+
+ <p>
+ NiFi doesn't support every feature that the ASN standard allows.
To alleviate problems when encountering ASN files with unsupported features,
+ NiFi can do additional preprocessing steps that creates modified
versions of the provided ASN files,
+ removing unsupported features in a way that makes them less strict
but otherwise should still be compatible with incoming data.
+ This feature can be switched on via the 'Do Additional
Preprocessing' property.
+ The original files will remain intact and new ones will be created
with the same names in a directory set in the 'Additional Preprocessing Output
Directory' property.
+ Please note that this is a best-effort attempt. It is also
strongly recommended to compare the resulting ASN files to the originals and
make sure they are still appropriate.
+ <br />
+ <br />
+ The following modification are applied:
+ <ol>
+ <li>
+ Constraints - Advanced constraints are not recognized as
valid ASN elements by NiFi. This step will try to remove <i>all</i> types of
constraints.
+ <br />E.g.
+ <pre>field [3] INTEGER(SIZE(1..8,...,10|12|20))
OPTIONAL</pre>
+ will be changed to
+ <pre>field [3] INTEGER OPTIONAL</pre>
+ </li>
+ <li>
+ Version brackets - NiFi will try to remove all version
brackets and leave all defined fields as OPTIONAL.
+ <br />E.g.
+ <pre>
+MyType ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+[[ -- comment2
+ integerField3 INTEGER,
+ integerField4 INTEGER,
+ integerField5 INTEGER ]]
+}
+ </pre>
+ will be changed to
+ <pre>
+MyType ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+ -- comment2
+ integerField3 INTEGER OPTIONAL,
+ integerField4 INTEGER OPTIONAL,
+ integerField5 INTEGER OPTIONAL
+}
+ </pre>
+ </li>
+ <li>
+ "Hugging" comments - This is not really an ASN feature
but a potential error. The double dash comment indicator "--" should be
separated from ASN elements.
+ <br />E.g.
+ <pre>field [0] INTEGER(1..8)--comment</pre>
+ will be changed to
+ <pre>field [0] INTEGER(1..8) --comment</pre>
+ </li>
+ </ol>
+ </p>
</body>
</html>
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngineTest.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngineTest.java
new file mode 100644
index 0000000000..d491765c54
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/AsnPreprocessorEngineTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.jasn1.preprocess;
+
+import org.apache.nifi.logging.ComponentLog;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringJoiner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class AsnPreprocessorEngineTest {
+ private AsnPreprocessorEngine testSubject;
+ private AsnPreprocessorEngine helper;
+
+ private AsnPreprocessor mockPreprocessor1;
+ private AsnPreprocessor mockPreprocessor2;
+ private List<AsnPreprocessor> preprocessors;
+
+ private ComponentLog log;
+
+ @TempDir
+ private File additionalPreprocessingOutputDirectory;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ mockPreprocessor1 = mock(AsnPreprocessor.class);
+ mockPreprocessor2 = mock(AsnPreprocessor.class);
+
+ preprocessors = Arrays.asList(
+ mockPreprocessor1,
+ mockPreprocessor2
+ );
+
+ log = mock(ComponentLog.class);
+
+ helper = mock(AsnPreprocessorEngine.class);
+ testSubject = new AsnPreprocessorEngine() {
+ @Override
+ List<String> readAsnLines(ComponentLog componentLog, String
inputFile, Path inputFilePath) {
+ return helper.readAsnLines(componentLog, inputFile,
inputFilePath);
+ }
+
+ @Override
+ void writePreprocessedAsn(ComponentLog componentLog, String
preprocessedAsn, Path preprocessedAsnPath) {
+ helper.writePreprocessedAsn(componentLog, preprocessedAsn,
preprocessedAsnPath);
+ }
+
+ @Override
+ List<AsnPreprocessor> getPreprocessors() {
+ return preprocessors;
+ }
+ };
+ }
+
+ @Test
+ void testPreprocess() {
+ // GIVEN
+ Path asnFile1Path = Paths.get("path", "to", "asn_file_1");
+ Path asnFile2Path = Paths.get("path", "to", "asn_file_2");
+
+ String asnFilesString = new StringJoiner(",")
+ .add(asnFile1Path.toString())
+ .add(asnFile2Path.toString())
+ .toString();
+
+ String outputDirectory = Paths.get("path", "to",
"directory_for_transformed_asn_files").toString();
+
+ List<String> originalLines1 = Arrays.asList("original_lines_1_1",
"original_lines_1_2");
+ List<String> preprocessedLines1_1 =
Arrays.asList("preprocessed_lines_1_1_1", "preprocessed_lines_1_1_2");
+ List<String> preprocessedLines1_2 = Arrays.asList("final_lines_1_1",
"final_lines_1_2");
+
+ List<String> originalLines2 = Arrays.asList("original_lines_2_1",
"original_lines_2_2");
+ List<String> preprocessedLines2_1 =
Arrays.asList("preprocessed_lines_2_1_1", "preprocessed_lines_2_1_2");
+ List<String> preprocessedLines2_2 = Arrays.asList("final_lines_2_1",
"final_lines_2_2");
+
+ when(helper.readAsnLines(eq(log), eq(asnFile1Path.toString()),
eq(asnFile1Path)))
+ .thenReturn(originalLines1);
+
when(mockPreprocessor1.preprocessAsn(originalLines1)).thenReturn(preprocessedLines1_1);
+
when(mockPreprocessor2.preprocessAsn(preprocessedLines1_1)).thenReturn(preprocessedLines1_2);
+
+ when(helper.readAsnLines(eq(log), eq(asnFile2Path.toString()),
eq(asnFile2Path)))
+ .thenReturn(originalLines2);
+
when(mockPreprocessor1.preprocessAsn(originalLines2)).thenReturn(preprocessedLines2_1);
+
when(mockPreprocessor2.preprocessAsn(preprocessedLines2_1)).thenReturn(preprocessedLines2_2);
+
+ String expected = new StringJoiner(",")
+ .add(Paths.get("path", "to",
"directory_for_transformed_asn_files", "asn_file_1").toString())
+ .add(Paths.get("path", "to",
"directory_for_transformed_asn_files", "asn_file_2").toString())
+ .toString();
+
+ // WHEN
+ String actual = testSubject.preprocess(log, asnFilesString,
outputDirectory);
+
+ // THEN
+ assertEquals(expected, actual);
+
+ verify(helper).readAsnLines(eq(log), eq(asnFile1Path.toString()),
eq(asnFile1Path));
+ verify(helper).readAsnLines(eq(log), eq(asnFile2Path.toString()),
eq(asnFile2Path));
+
+ verify(mockPreprocessor1).preprocessAsn(originalLines1);
+ verify(mockPreprocessor2).preprocessAsn(preprocessedLines1_1);
+
+ verify(mockPreprocessor1).preprocessAsn(originalLines2);
+ verify(mockPreprocessor2).preprocessAsn(preprocessedLines2_1);
+
+ verify(helper).writePreprocessedAsn(
+ eq(log),
+ eq("final_lines_1_1" + System.lineSeparator() +
"final_lines_1_2"),
+ eq(Paths.get("path", "to",
"directory_for_transformed_asn_files", "asn_file_1"))
+ );
+
+ verify(helper).writePreprocessedAsn(
+ eq(log),
+ eq("final_lines_2_1" + System.lineSeparator() +
"final_lines_2_2"),
+ eq(Paths.get("path", "to",
"directory_for_transformed_asn_files", "asn_file_2"))
+ );
+ }
+
+ @Test
+ void testComplexPreprocessing() throws Exception {
+ testSubject = new AsnPreprocessorEngine();
+
+ String input = "test_complex_for_preprocessing.asn";
+
+
+ String preprocessedFile = testSubject.preprocess(
+ log,
+ new
File(getClass().getClassLoader().getResource(input).toURI()).getAbsolutePath(),
+ additionalPreprocessingOutputDirectory.getAbsolutePath()
+ );
+
+ String expected = new
String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("preprocessed_"
+ input).toURI())), StandardCharsets.UTF_8)
+ .replace("\n", System.lineSeparator());
+
+ String actual = new
String(Files.readAllBytes(Paths.get(preprocessedFile)), StandardCharsets.UTF_8);
+
+ assertEquals(expected, actual);
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/AbstractAsnPreprocessorTest.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/AbstractAsnPreprocessorTest.java
new file mode 100644
index 0000000000..9bb9c3c605
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/AbstractAsnPreprocessorTest.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.apache.nifi.jasn1.preprocess.AsnPreprocessor;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public abstract class AbstractAsnPreprocessorTest {
+ protected AsnPreprocessor testSubject;
+
+ protected void testPreprocess(String input) throws IOException,
URISyntaxException {
+ // GIVEN
+ List<String> lines =
Files.readAllLines(Paths.get(getClass().getClassLoader().getResource(input).toURI()));
+
+ // WHEN
+ String actual = testSubject.preprocessAsn(lines)
+ .stream()
+ .collect(Collectors.joining(System.lineSeparator()));
+
+ // THEN
+ String expected = new
String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("preprocessed_"
+ input).toURI())), StandardCharsets.UTF_8)
+ .replace("\n", System.lineSeparator());
+
+ assertEquals(expected, actual);
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessorTest.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessorTest.java
new file mode 100644
index 0000000000..7480210d57
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/ConstraintAsnPreprocessorTest.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class ConstraintAsnPreprocessorTest extends AbstractAsnPreprocessorTest
{
+ @BeforeEach
+ void setUp() {
+ testSubject = new ConstraintAsnPreprocessor();
+ }
+
+ @Test
+ void testPreprocessConstraints() throws Exception {
+ testPreprocess("test_constraints.asn");
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessorTest.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessorTest.java
new file mode 100644
index 0000000000..40d5850a5f
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/HuggingCommentAsnPreprocessorTest.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class HuggingCommentAsnPreprocessorTest extends
AbstractAsnPreprocessorTest {
+ @BeforeEach
+ void setUp() {
+ testSubject = new HuggingCommentAsnPreprocessor();
+ }
+
+ @Test
+ void testPreprocessHuggingComment() throws Exception {
+ testPreprocess("test_hugging_comment.asn");
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessorTest.java
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessorTest.java
new file mode 100644
index 0000000000..8ff05f2067
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/java/org/apache/nifi/jasn1/preprocess/preprocessors/VersionBracketAsnPreprocessorTest.java
@@ -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.jasn1.preprocess.preprocessors;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class VersionBracketAsnPreprocessorTest extends
AbstractAsnPreprocessorTest {
+ @BeforeEach
+ void setUp() {
+ testSubject = new VersionBracketAsnPreprocessor();
+ }
+
+ @Test
+ void testPreprocessVersionBracket() throws Exception {
+ testPreprocess("test_version_bracket.asn");
+ }
+}
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_complex_for_preprocessing.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_complex_for_preprocessing.asn
new file mode 100644
index 0000000000..98222c7c98
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_complex_for_preprocessing.asn
@@ -0,0 +1,15 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyType ::= SEQUENCE {
+ field1 [0] INTEGER , --Comment
+ -- comment2
+ field2 INTEGER OPTIONAL,
+ field3 INTEGER OPTIONAL,
+ field4 INTEGER OPTIONAL
+}
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_constraints.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_constraints.asn
new file mode 100644
index 0000000000..3620a4269d
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_constraints.asn
@@ -0,0 +1,27 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyTypeWithFieldConstraints := SEQUENCE {
+ field1 [0] INTEGER ,
+ field2 [1] INTEGER ,
+ field3 [2] INTEGER ,
+ field4 [3] INTEGER OPTIONAL
+}
+
+MyTypeWithSequenceSizeConstraint ::= SEQUENCE SIZE OF MyType
+
+
+
+MyTypeWithComponents ::=
+ MyType
+
+
+
+
+
+
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_hugging_comment.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_hugging_comment.asn
new file mode 100644
index 0000000000..648d9bfcc2
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_hugging_comment.asn
@@ -0,0 +1,12 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyTypeWithHuggingComment := SEQUENCE {
+ field [0] INTEGER(1..8) --comment
+}
+
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_version_bracket.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_version_bracket.asn
new file mode 100644
index 0000000000..7b2a4b0af5
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/preprocessed_test_version_bracket.asn
@@ -0,0 +1,44 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+VersionBracket1LineSingleField ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ...,
+ integerField3 INTEGER OPTIONAL
+}
+
+VersionBracketCommentMultiLine ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+ -- comment2
+ integerField3 INTEGER OPTIONAL,
+ integerField4 INTEGER OPTIONAL,
+ integerField5 INTEGER OPTIONAL
+}
+
+VersionBracketMultiLineFirstHasField ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+ integerField3 INTEGER OPTIONAL,
+ integerField4 INTEGER OPTIONAL,
+ integerField5 INTEGER OPTIONAL
+}
+
+TypeWithVersionBracketMultiLineBracketsAlone ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ...,
+
+ integerField3 INTEGER OPTIONAL,
+ integerField4 INTEGER OPTIONAL,
+ integerField5 INTEGER OPTIONAL
+
+}
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_complex_for_preprocessing.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_complex_for_preprocessing.asn
new file mode 100644
index 0000000000..5fcbf2d8fa
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_complex_for_preprocessing.asn
@@ -0,0 +1,15 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyType ::= SEQUENCE {
+ field1 [0] INTEGER(1..8),--Comment
+[[ -- comment2
+ field2 INTEGER,
+ field3 INTEGER,
+ field4 INTEGER ]]
+}
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_constraints.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_constraints.asn
new file mode 100644
index 0000000000..bcf696dc4a
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_constraints.asn
@@ -0,0 +1,27 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyTypeWithFieldConstraints := SEQUENCE {
+ field1 [0] INTEGER(1..8),
+ field2 [1] INTEGER(1..8,...),
+ field3 [2] INTEGER(1..8|100-200),
+ field4 [3] INTEGER(SIZE(1..8,...,10|12|20)) OPTIONAL
+}
+
+MyTypeWithSequenceSizeConstraint ::= SEQUENCE SIZE(1..8) OF MyType
+
+
+
+MyTypeWithComponents ::=
+ MyType
+ (WITH COMPONENTS {
+ ...,
+
+ -- some comment
+ field1 ABSENT
+ }|WITH COMPONENTS {..., field2 PRESENT})
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_hugging_comment.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_hugging_comment.asn
new file mode 100644
index 0000000000..7d7194c508
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_hugging_comment.asn
@@ -0,0 +1,12 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+MyTypeWithHuggingComment := SEQUENCE {
+ field [0] INTEGER(1..8)--comment
+}
+
+
+END
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_version_bracket.asn
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_version_bracket.asn
new file mode 100644
index 0000000000..d21507716d
--- /dev/null
+++
b/nifi-nar-bundles/nifi-asn1-bundle/nifi-asn1-services/src/test/resources/test_version_bracket.asn
@@ -0,0 +1,44 @@
+ORG-APACHE-NIFI-JASN1-TEST
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+VersionBracket1LineSingleField ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ...,
+[[ integerField3 INTEGER ]]
+}
+
+VersionBracketCommentMultiLine ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+[[ -- comment2
+ integerField3 INTEGER,
+ integerField4 INTEGER,
+ integerField5 INTEGER ]]
+}
+
+VersionBracketMultiLineFirstHasField ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ..., -- comment1
+[[ integerField3 INTEGER,
+ integerField4 INTEGER,
+ integerField5 INTEGER ]]
+}
+
+TypeWithVersionBracketMultiLineBracketsAlone ::= SEQUENCE {
+ integerField1 INTEGER,
+ integerField2 INTEGER,
+ ...,
+[[
+ integerField3 INTEGER,
+ integerField4 INTEGER,
+ integerField5 INTEGER
+]]
+}
+
+END
\ No newline at end of file