Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -283,25 +283,41 @@ public List<ConfigVerificationResult> verify(final FlowContext flowContext) {
}

@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) {
Expand Down Expand Up @@ -339,7 +355,7 @@ private void validate(final FlowContext context, final ProcessGroupFacade group,
}

for (final ProcessGroupFacade childGroup : group.getProcessGroups()) {
validate(context, childGroup, validationContext, validationResults);
validateComponents(context, childGroup, validationContext, validationResults);
}
}

Expand Down Expand Up @@ -425,33 +441,11 @@ private void forEachConnection(final ProcessGroupFacade group, final Consumer<Co
}
}

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<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand Down Expand Up @@ -210,6 +211,24 @@ private ValidationResult validateType(final String value) {
.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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface Secret {

String getName();

String getDescription();

String getValue();

}

This file was deleted.

This file was deleted.

55 changes: 55 additions & 0 deletions src/main/java/org/apache/nifi/parameter/ParameterProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
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
Expand Down Expand Up @@ -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;
}
}