blob: a2ebdf7f9f6067b7f842f1e807e460099a8f62a5 [file] [log] [blame]
/*
* 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.processor;
import org.apache.nifi.attribute.expression.language.PreparedQuery;
import org.apache.nifi.attribute.expression.language.Query;
import org.apache.nifi.attribute.expression.language.Query.Range;
import org.apache.nifi.attribute.expression.language.StandardExpressionLanguageCompiler;
import org.apache.nifi.attribute.expression.language.StandardPropertyValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.resource.ResourceContext;
import org.apache.nifi.components.resource.StandardResourceContext;
import org.apache.nifi.components.resource.StandardResourceReferenceFactory;
import org.apache.nifi.components.validation.AbstractValidationContext;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.controller.PropertyConfiguration;
import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.ControllerServiceProvider;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.expression.ExpressionLanguageCompiler;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterReference;
import org.apache.nifi.registry.VariableRegistry;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
public class StandardValidationContext extends AbstractValidationContext implements ValidationContext {
private final ControllerServiceProvider controllerServiceProvider;
private final Map<PropertyDescriptor, PropertyConfiguration> properties;
private final Map<PropertyDescriptor, PreparedQuery> preparedQueries;
private final Map<String, Boolean> expressionLanguageSupported;
private final String annotationData;
private final VariableRegistry variableRegistry;
private final String groupId;
private final String componentId;
private final ParameterContext parameterContext;
private final AtomicReference<Map<PropertyDescriptor, String>> effectiveValuesRef = new AtomicReference<>();
private final boolean validateConnections;
public StandardValidationContext(
final ControllerServiceProvider controllerServiceProvider,
final Map<PropertyDescriptor, PropertyConfiguration> properties,
final String annotationData,
final String groupId,
final String componentId,
final VariableRegistry variableRegistry,
final ParameterContext parameterContext,
final boolean validateConnections) {
super(parameterContext, properties);
this.controllerServiceProvider = controllerServiceProvider;
this.properties = new HashMap<>(properties);
this.annotationData = annotationData;
this.variableRegistry = variableRegistry;
this.groupId = groupId;
this.componentId = componentId;
this.parameterContext = parameterContext;
this.validateConnections = validateConnections;
preparedQueries = new HashMap<>(properties.size());
for (final Map.Entry<PropertyDescriptor, PropertyConfiguration> entry : properties.entrySet()) {
final PropertyDescriptor desc = entry.getKey();
final PropertyConfiguration configuration = entry.getValue();
String value = (configuration == null) ? null : configuration.getEffectiveValue(parameterContext);
if (value == null) {
value = desc.getDefaultValue();
}
final PreparedQuery pq = Query.prepare(value);
preparedQueries.put(desc, pq);
}
expressionLanguageSupported = new HashMap<>(properties.size());
for (final PropertyDescriptor descriptor : properties.keySet()) {
expressionLanguageSupported.put(descriptor.getName(), descriptor.isExpressionLanguageSupported());
}
}
@Override
public PropertyValue newPropertyValue(final String rawValue) {
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), null);
return new StandardPropertyValue(resourceContext, rawValue, controllerServiceProvider, parameterContext, Query.prepareWithParametersPreEvaluated(rawValue), variableRegistry);
}
@Override
public ExpressionLanguageCompiler newExpressionLanguageCompiler() {
return new StandardExpressionLanguageCompiler(variableRegistry, parameterContext);
}
@Override
public ValidationContext getControllerServiceValidationContext(final ControllerService controllerService) {
final ControllerServiceNode serviceNode = controllerServiceProvider.getControllerServiceNode(controllerService.getIdentifier());
final ProcessGroup serviceGroup = serviceNode.getProcessGroup();
final String serviceGroupId = serviceGroup == null ? null : serviceGroup.getIdentifier();
return new StandardValidationContext(controllerServiceProvider, serviceNode.getProperties(), serviceNode.getAnnotationData(), serviceGroupId,
serviceNode.getIdentifier(), variableRegistry, serviceNode.getProcessGroup().getParameterContext(), validateConnections);
}
@Override
public PropertyValue getProperty(final PropertyDescriptor property) {
final PropertyConfiguration configuredValue = properties.get(property);
final String effectiveValue = configuredValue == null ? property.getDefaultValue() : configuredValue.getEffectiveValue(parameterContext);
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), property);
return new StandardPropertyValue(resourceContext, effectiveValue, controllerServiceProvider, parameterContext, preparedQueries.get(property), variableRegistry);
}
@Override
public Map<PropertyDescriptor, String> getProperties() {
final Map<PropertyDescriptor, String> effectiveValues = effectiveValuesRef.get();
if (effectiveValues != null) {
return effectiveValues;
}
final Map<PropertyDescriptor, String> valueMap = new LinkedHashMap<>();
for (final Map.Entry<PropertyDescriptor, PropertyConfiguration> entry : this.properties.entrySet()) {
final PropertyDescriptor descriptor = entry.getKey();
final PropertyConfiguration configuration = entry.getValue();
final String value = configuration == null ? descriptor.getDefaultValue() : configuration.getEffectiveValue(parameterContext);
valueMap.put(entry.getKey(), value);
}
final Map<PropertyDescriptor, String> immutableValueMap = Collections.unmodifiableMap(valueMap);
effectiveValuesRef.compareAndSet(null, immutableValueMap);
return immutableValueMap;
}
@Override
public Map<String, String> getAllProperties() {
final Map<String,String> propValueMap = new LinkedHashMap<>();
for (final Map.Entry<PropertyDescriptor, String> entry : getProperties().entrySet()) {
propValueMap.put(entry.getKey().getName(), entry.getValue());
}
return propValueMap;
}
@Override
public String getAnnotationData() {
return annotationData;
}
@Override
public ControllerServiceLookup getControllerServiceLookup() {
return new ComponentSpecificControllerServiceLookup(controllerServiceProvider, componentId, groupId);
}
@Override
public boolean isValidationRequired(final ControllerService service) {
// No need to validate services that are already enabled.
final ControllerServiceState serviceState = controllerServiceProvider.getControllerServiceNode(service.getIdentifier()).getState();
if (serviceState == ControllerServiceState.ENABLED || serviceState == ControllerServiceState.ENABLING) {
return false;
}
return true;
}
@Override
public boolean isExpressionLanguagePresent(final String value) {
if (value == null) {
return false;
}
final List<Range> elRanges = Query.extractExpressionRanges(value);
return (elRanges != null && !elRanges.isEmpty());
}
@Override
public boolean isExpressionLanguageSupported(final String propertyName) {
final Boolean supported = expressionLanguageSupported.get(propertyName);
return Boolean.TRUE.equals(supported);
}
@Override
public String getProcessGroupIdentifier() {
return groupId;
}
@Override
public Collection<String> getReferencedParameters(final String propertyName) {
final PropertyDescriptor descriptor = new PropertyDescriptor.Builder().name(propertyName).build();
final PropertyConfiguration configuration = this.properties.get(descriptor);
if (configuration == null) {
return Collections.emptyList();
}
final List<ParameterReference> references = configuration.getParameterReferences();
final List<String> parameterNames = references.stream().map(ParameterReference::getParameterName).collect(Collectors.toList());
return parameterNames;
}
@Override
public boolean isParameterDefined(final String parameterName) {
if (parameterContext == null) {
return false;
}
return parameterContext.getParameter(parameterName).isPresent();
}
@Override
public boolean isParameterSet(final String parameterName) {
if (parameterContext == null) {
return false;
}
final Optional<Parameter> parameterOption = parameterContext.getParameter(parameterName);
if (!parameterOption.isPresent()) {
return false;
}
final String value = parameterOption.get().getValue();
return value != null;
}
@Override
public boolean isValidateConnections() {
return validateConnections;
}
@Override
public String toString() {
return "StandardValidationContext[componentId=" + componentId + ", properties=" + properties + "]";
}
}