This is an automated email from the ASF dual-hosted git repository.
mcgilman pushed a commit to branch NIFI-15258
in repository https://gitbox.apache.org/repos/asf/nifi-api.git
The following commit(s) were added to refs/heads/NIFI-15258 by this push:
new b390ec4 NIFI-15312: Moved SecretsProvider / SecretsManager to
framework instead of api; added description to Secret and updated
ParameterProvider to allow more specific fetching of parameters; cleaned up
Connector validation logic (#29)
b390ec4 is described below
commit b390ec47af76781d02f46afcce465f0fe3cf87b2
Author: Mark Payne <[email protected]>
AuthorDate: Fri Dec 12 18:00:53 2025 -0500
NIFI-15312: Moved SecretsProvider / SecretsManager to framework instead of
api; added description to Secret and updated ParameterProvider to allow more
specific fetching of parameters; cleaned up Connector validation logic (#29)
---
.../components/connector/AbstractConnector.java | 72 ++++++++++------------
.../connector/ConnectorPropertyDescriptor.java | 19 ++++++
.../apache/nifi/components/connector/Secret.java | 2 +
.../nifi/components/connector/SecretProvider.java | 33 ----------
.../nifi/components/connector/SecretsManager.java | 33 ----------
.../apache/nifi/parameter/ParameterProvider.java | 55 +++++++++++++++++
6 files changed, 109 insertions(+), 105 deletions(-)
diff --git
a/src/main/java/org/apache/nifi/components/connector/AbstractConnector.java
b/src/main/java/org/apache/nifi/components/connector/AbstractConnector.java
index 4cfac54..6db3acc 100644
--- a/src/main/java/org/apache/nifi/components/connector/AbstractConnector.java
+++ b/src/main/java/org/apache/nifi/components/connector/AbstractConnector.java
@@ -283,25 +283,41 @@ public abstract class AbstractConnector implements
Connector {
}
@Override
- public List<ValidationResult> validate(final FlowContext context, final
ConnectorValidationContext validationContext) {
- final List<ValidationResult> validationResults = new ArrayList<>();
- validate(context, context.getRootGroup(), validationContext,
validationResults);
- return validationResults;
- }
+ public List<ValidationResult> validate(final FlowContext flowContext,
final ConnectorValidationContext validationContext) {
+ final ConnectorConfigurationContext configContext =
flowContext.getConfigurationContext();
+ final List<ValidationResult> results = new ArrayList<>();
+ final List<ConfigurationStep> configurationSteps =
getConfigurationSteps(flowContext);
- private void validate(final FlowContext context, final ProcessGroupFacade
group, final ConnectorValidationContext validationContext, final
List<ValidationResult> validationResults) {
- final List<ValidationResult> connectorPropertiesResults =
validate(context, context.getConfigurationContext(), validationContext);
- if (!connectorPropertiesResults.isEmpty()) {
- connectorPropertiesResults.stream()
- .filter(result -> !result.isValid())
- .forEach(validationResults::add);
+ for (final ConfigurationStep configurationStep : configurationSteps) {
+ results.addAll(validateConfigurationStep(configurationStep,
configContext, validationContext));
+ }
- // If any invalid results on the connector configuration itself,
do not proceed with further validation of components
- if (!validationResults.isEmpty()) {
- return;
+ // only run customValidate if regular validation is successful. This
allows Processor developers to not have to check
+ // if values are null or invalid so that they can focus only on the
interaction between the properties, etc.
+ if (results.isEmpty()) {
+ final Collection<ValidationResult> customResults =
customValidate(configContext);
+ if (customResults != null) {
+ for (final ValidationResult result : customResults) {
+ if (!result.isValid()) {
+ results.add(result);
+ }
+ }
}
}
+ return results;
+ }
+
+
+ protected List<ValidationResult> validateComponents(final FlowContext
context, final ProcessGroupFacade group, final ConnectorValidationContext
validationContext) {
+ final List<ValidationResult> validationResults = new ArrayList<>();
+ validateComponents(context, group, validationContext,
validationResults);
+ return validationResults;
+ }
+
+ private void validateComponents(final FlowContext context, final
ProcessGroupFacade group, final ConnectorValidationContext validationContext,
+ final List<ValidationResult> validationResults) {
+
for (final ProcessorFacade processor : group.getProcessors()) {
final List<ValidationResult> processorResults =
processor.validate();
for (final ValidationResult result : processorResults) {
@@ -339,7 +355,7 @@ public abstract class AbstractConnector implements
Connector {
}
for (final ProcessGroupFacade childGroup : group.getProcessGroups()) {
- validate(context, childGroup, validationContext,
validationResults);
+ validateComponents(context, childGroup, validationContext,
validationResults);
}
}
@@ -425,33 +441,11 @@ public abstract class AbstractConnector implements
Connector {
}
}
- private List<ValidationResult> validate(final FlowContext workingContext,
final ConnectorConfigurationContext context, final ConnectorValidationContext
validationContext) {
- final List<ValidationResult> results = new ArrayList<>();
- final List<ConfigurationStep> configurationSteps =
getConfigurationSteps(workingContext);
-
- for (final ConfigurationStep configurationStep : configurationSteps) {
- results.addAll(validateConfigurationStep(configurationStep,
context, validationContext));
- }
-
- // only run customValidate if regular validation is successful. This
allows Processor developers to not have to check
- // if values are null or invalid so that they can focus only on the
interaction between the properties, etc.
- if (results.isEmpty()) {
- final Collection<ValidationResult> customResults =
customValidate(context);
- if (customResults != null) {
- for (final ValidationResult result : customResults) {
- if (!result.isValid()) {
- results.add(result);
- }
- }
- }
- }
-
- return results;
- }
@Override
public List<ValidationResult> validateConfigurationStep(final
ConfigurationStep configurationStep, final ConnectorConfigurationContext
configurationContext,
- final ConnectorValidationContext validationContext) {
+ final ConnectorValidationContext validationContext) {
+
final String stepName = configurationStep.getName();
final List<ValidationResult> results = new ArrayList<>();
diff --git
a/src/main/java/org/apache/nifi/components/connector/ConnectorPropertyDescriptor.java
b/src/main/java/org/apache/nifi/components/connector/ConnectorPropertyDescriptor.java
index f765d11..209039b 100644
---
a/src/main/java/org/apache/nifi/components/connector/ConnectorPropertyDescriptor.java
+++
b/src/main/java/org/apache/nifi/components/connector/ConnectorPropertyDescriptor.java
@@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -210,6 +211,24 @@ public final class ConnectorPropertyDescriptor {
.build();
}
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final ConnectorPropertyDescriptor that = (ConnectorPropertyDescriptor)
o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
+ @Override
+ public String toString() {
+ return "ConnectorPropertyDescriptor[name=" + name + "]";
+ }
public static final class Builder {
private String name;
diff --git a/src/main/java/org/apache/nifi/components/connector/Secret.java
b/src/main/java/org/apache/nifi/components/connector/Secret.java
index 4d6e8c5..5b50ea4 100644
--- a/src/main/java/org/apache/nifi/components/connector/Secret.java
+++ b/src/main/java/org/apache/nifi/components/connector/Secret.java
@@ -25,6 +25,8 @@ public interface Secret {
String getName();
+ String getDescription();
+
String getValue();
}
diff --git
a/src/main/java/org/apache/nifi/components/connector/SecretProvider.java
b/src/main/java/org/apache/nifi/components/connector/SecretProvider.java
deleted file mode 100644
index 22849a5..0000000
--- a/src/main/java/org/apache/nifi/components/connector/SecretProvider.java
+++ /dev/null
@@ -1,33 +0,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.
- */
-
-package org.apache.nifi.components.connector;
-
-import java.io.IOException;
-import java.util.List;
-
-public interface SecretProvider {
-
- String getProviderId();
-
- String getProviderName();
-
- List<Secret> getAllSecrets() throws IOException;
-
- List<Secret> getSecrets(List<String> fullyQualifiedSecretNames) throws
IOException;
-
-}
diff --git
a/src/main/java/org/apache/nifi/components/connector/SecretsManager.java
b/src/main/java/org/apache/nifi/components/connector/SecretsManager.java
deleted file mode 100644
index 564b717..0000000
--- a/src/main/java/org/apache/nifi/components/connector/SecretsManager.java
+++ /dev/null
@@ -1,33 +0,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.
- */
-
-package org.apache.nifi.components.connector;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-public interface SecretsManager {
-
- Optional<Secret> getSecret(SecretReference secretReference) throws
IOException;
-
- List<Secret> getAllSecrets() throws IOException;
-
- Set<SecretProvider> getSecretProviders();
-
-}
diff --git a/src/main/java/org/apache/nifi/parameter/ParameterProvider.java
b/src/main/java/org/apache/nifi/parameter/ParameterProvider.java
index 7179bfb..c542e61 100644
--- a/src/main/java/org/apache/nifi/parameter/ParameterProvider.java
+++ b/src/main/java/org/apache/nifi/parameter/ParameterProvider.java
@@ -22,7 +22,10 @@ import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.reporting.InitializationException;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Defines a provider that is responsible for fetching from an external source
Parameters with
@@ -84,4 +87,56 @@ public interface ParameterProvider extends
ConfigurableComponent {
* @throws IOException if there is an I/O problem while fetching the
Parameters
*/
List<ParameterGroup> fetchParameters(ConfigurationContext context) throws
IOException;
+
+ /**
+ * Fetches named groups of parameters from an external source, filtering
to only include the specified parameter names.
+ * It is up to the implementation to determine how a fully qualified
parameter name maps to a group and parameter name
+ * and to optimize the fetching accordingly. The default implementation
fetches all parameters and filters them, assuming
+ * that the fully qualified parameter name is of the form
"GroupName.ParameterName".
+ *
+ * @param context The <code>ConfigurationContext</code>for the provider
+ * @param fullyQualifiedParameterNames the fully qualified names of the
parameters to fetch
+ * @return A list of fetched Parameter groups containing only the
specified parameters
+ * @throws IOException if there is an I/O problem while fetching the
Parameters
+ */
+ default List<ParameterGroup> fetchParameters(ConfigurationContext context,
List<String> fullyQualifiedParameterNames) throws IOException {
+ final List<ParameterGroup> allGroups = fetchParameters(context);
+ final List<ParameterGroup> filteredGroups = new ArrayList<>();
+
+ for (final ParameterGroup group : allGroups) {
+ // Determine which parameter names are desired from this group
+ final List<String> desiredParameterNames = new ArrayList<>();
+ final String prefix = group.getGroupName() + ".";
+ for (final String fullyQualifiedParameterName :
fullyQualifiedParameterNames) {
+ if (fullyQualifiedParameterName.startsWith(prefix)) {
+ final String secretName =
fullyQualifiedParameterName.substring(prefix.length());
+ desiredParameterNames.add(secretName);
+ }
+ }
+
+ // If no parameters are desired from this group, skip it
+ if (desiredParameterNames.isEmpty()) {
+ continue;
+ }
+
+ // Create a HashSet for quick lookup
+ final Set<String> parameterNameSet = new
HashSet<>(desiredParameterNames);
+ final List<Parameter> filteredParameters = new ArrayList<>();
+ for (final Parameter parameter : group.getParameters()) {
+ if
(!parameterNameSet.contains(parameter.getDescriptor().getName())) {
+ continue;
+ }
+
+ filteredParameters.add(parameter);
+ }
+
+ // If we found any desired parameters, add them to the result
+ if (!filteredParameters.isEmpty()) {
+ filteredGroups.add(new ParameterGroup(group.getGroupName(),
filteredParameters));
+ }
+ }
+
+ // Return the filtered groups
+ return filteredGroups;
+ }
}