Search in sources :

Example 6 with Action

use of org.apache.nifi.update.attributes.Action in project nifi by apache.

the class UpdateAttribute method customValidate.

@Override
protected Collection<ValidationResult> customValidate(final ValidationContext context) {
    final List<ValidationResult> reasons = new ArrayList<>(super.customValidate(context));
    if (!context.getProperty(STORE_STATE).getValue().equals(DO_NOT_STORE_STATE)) {
        String initValue = context.getProperty(STATEFUL_VARIABLES_INIT_VALUE).getValue();
        if (initValue == null) {
            reasons.add(new ValidationResult.Builder().subject(STATEFUL_VARIABLES_INIT_VALUE.getDisplayName()).valid(false).explanation("initial state value must be set if the processor is configured to store state.").build());
        }
    }
    Criteria criteria = null;
    try {
        criteria = CriteriaSerDe.deserialize(context.getAnnotationData());
    } catch (IllegalArgumentException iae) {
        reasons.add(new ValidationResult.Builder().valid(false).explanation("Unable to deserialize the update criteria." + iae.getMessage()).build());
    }
    // if there is criteria, validate it
    if (criteria != null) {
        final List<Rule> rules = criteria.getRules();
        if (rules == null) {
            reasons.add(new ValidationResult.Builder().valid(false).explanation("Update criteria has been specified by no rules were found.").build());
        } else {
            // validate the each rule
            for (final Rule rule : rules) {
                if (rule.getName() == null || rule.getName().trim().isEmpty()) {
                    reasons.add(new ValidationResult.Builder().valid(false).explanation("A rule name was not specified.").build());
                }
                // validate each condition
                final Set<Condition> conditions = rule.getConditions();
                if (conditions == null) {
                    reasons.add(new ValidationResult.Builder().valid(false).explanation(String.format("No conditions for rule '%s' found.", rule.getName())).build());
                } else {
                    for (final Condition condition : conditions) {
                        if (condition.getExpression() == null) {
                            reasons.add(new ValidationResult.Builder().valid(false).explanation(String.format("No expression for a condition in rule '%s' was found.", rule.getName())).build());
                        } else {
                            final String expression = condition.getExpression().trim();
                            reasons.add(StandardValidators.createAttributeExpressionLanguageValidator(AttributeExpression.ResultType.BOOLEAN, false).validate(String.format("Condition for rule '%s'.", rule.getName()), expression, context));
                        }
                    }
                }
                // validate each action
                final Set<Action> actions = rule.getActions();
                if (actions == null) {
                    reasons.add(new ValidationResult.Builder().valid(false).explanation(String.format("No actions for rule '%s' found.", rule.getName())).build());
                } else {
                    for (final Action action : actions) {
                        if (action.getAttribute() == null) {
                            reasons.add(new ValidationResult.Builder().valid(false).explanation(String.format("An action in rule '%s' is missing the attribute name.", rule.getName())).build());
                        } else if (action.getValue() == null) {
                            reasons.add(new ValidationResult.Builder().valid(false).explanation(String.format("No value for attribute '%s' in rule '%s' was found.", action.getAttribute(), rule.getName())).build());
                        } else {
                            reasons.add(StandardValidators.createAttributeExpressionLanguageValidator(AttributeExpression.ResultType.STRING, true).validate(String.format("Action for rule '%s'.", rule.getName()), action.getValue(), context));
                        }
                    }
                }
            }
        }
    }
    return reasons;
}
Also used : Condition(org.apache.nifi.update.attributes.Condition) Action(org.apache.nifi.update.attributes.Action) ArrayList(java.util.ArrayList) Criteria(org.apache.nifi.update.attributes.Criteria) ValidationResult(org.apache.nifi.components.ValidationResult) Rule(org.apache.nifi.update.attributes.Rule)

Example 7 with Action

use of org.apache.nifi.update.attributes.Action in project nifi by apache.

the class UpdateAttribute method executeActions.

// Executes the specified action on the specified flowfile.
private FlowFile executeActions(final ProcessSession session, final ProcessContext context, final List<Rule> rules, final Map<String, Action> defaultActions, final FlowFile flowfile, final Map<String, String> stateInitialAttributes, final Map<String, String> stateWorkingAttributes) {
    final ComponentLog logger = getLogger();
    final Map<String, Action> actions = new HashMap<>(defaultActions);
    final String ruleName = (rules == null || rules.isEmpty()) ? "default" : rules.get(rules.size() - 1).getName();
    // if a rule matched, get its actions and possible overwrite the default ones
    if (rules != null && rules.size() > 0) {
        // subsequent matching rules will take precedence over previously matching rules and default values
        for (final Rule rule : rules) {
            for (final Action action : rule.getActions()) {
                // store the action and overwrite the previous value (from the defaults or a previously matching rule)
                actions.put(action.getAttribute(), action);
            }
        }
        // add an action for the matched rule - when matching multiple rules against
        // the original flowfile (use original) this will leave the last matching
        // rule's name as the value of this attribute. this decision was made since
        // this would be the behavior if they user chained multiple UpdateAttributes
        // together with 'use clone' specified
        final Action matchedRuleAction = new Action();
        matchedRuleAction.setAttribute(getClass().getSimpleName() + ".matchedRule");
        matchedRuleAction.setValue(ruleName);
        actions.put(matchedRuleAction.getAttribute(), matchedRuleAction);
    }
    // attribute values that will be applied to the flow file
    final Map<String, String> attributesToUpdate = new HashMap<>(actions.size());
    final Set<String> attributesToDelete = new HashSet<>(actions.size());
    // go through each action
    boolean debugEnabled = this.debugEnabled;
    for (final Action action : actions.values()) {
        String attribute = action.getAttribute();
        if (DELETE_ATTRIBUTES_EXPRESSION_NAME.equals(attribute)) {
            try {
                final String actionValue = action.getValue();
                final String regex = (actionValue == null) ? null : getPropertyValue(actionValue, context).evaluateAttributeExpressions(flowfile).getValue();
                if (regex != null) {
                    Pattern pattern = Pattern.compile(regex);
                    final Set<String> attributeKeys = flowfile.getAttributes().keySet();
                    for (final String key : attributeKeys) {
                        if (pattern.matcher(key).matches()) {
                            // log if appropriate
                            if (debugEnabled) {
                                logger.debug(String.format("%s deleting attribute '%s' for %s per regex '%s'.", this, key, flowfile, regex));
                            }
                            attributesToDelete.add(key);
                        }
                    }
                    // No point in updating if they will be removed
                    attributesToUpdate.keySet().removeAll(attributesToDelete);
                }
            } catch (final Exception e) {
                logger.error(String.format("Unable to delete attribute '%s' while processing FlowFile '%s' .", attribute, flowfile));
                throw new ProcessException(String.format("Unable to delete attribute '%s': %s.", attribute, e), e);
            }
        } else {
            boolean notDeleted = !attributesToDelete.contains(attribute);
            boolean setStatefulAttribute = stateInitialAttributes != null && !attribute.equals("UpdateAttribute.matchedRule");
            if (notDeleted || setStatefulAttribute) {
                try {
                    final String newAttributeValue = getPropertyValue(action.getValue(), context).evaluateAttributeExpressions(flowfile, null, null, stateInitialAttributes).getValue();
                    // log if appropriate
                    if (debugEnabled) {
                        logger.debug(String.format("%s setting attribute '%s' = '%s' for %s per rule '%s'.", this, attribute, newAttributeValue, flowfile, ruleName));
                    }
                    if (setStatefulAttribute) {
                        stateWorkingAttributes.put(attribute, newAttributeValue);
                    }
                    // No point in updating if it will be removed
                    if (notDeleted) {
                        attributesToUpdate.put(attribute, newAttributeValue);
                    }
                // Capture Exception thrown when evaluating the Expression Language
                } catch (final Exception e) {
                    logger.error(String.format("Could not evaluate the FlowFile '%s' against expression '%s' " + "defined by DynamicProperty '%s' due to '%s'", flowfile, action.getValue(), attribute, e.getLocalizedMessage()));
                    throw new ProcessException(String.format("Unable to evaluate new value for attribute '%s': %s.", attribute, e), e);
                }
            }
        }
    }
    // If the 'alternate.identifier' attribute is added, then we want to create an ADD_INFO provenance event.
    final String alternateIdentifierAdd = attributesToUpdate.get(CoreAttributes.ALTERNATE_IDENTIFIER.key());
    if (alternateIdentifierAdd != null) {
        try {
            final URI uri = new URI(alternateIdentifierAdd);
            final String namespace = uri.getScheme();
            if (namespace != null) {
                final String identifier = alternateIdentifierAdd.substring(Math.min(namespace.length() + 1, alternateIdentifierAdd.length() - 1));
                session.getProvenanceReporter().associate(flowfile, namespace, identifier);
            }
        } catch (final URISyntaxException e) {
        }
    }
    // update and delete the FlowFile attributes
    FlowFile returnFlowfile = flowfile;
    if (attributesToUpdate.size() > 0) {
        returnFlowfile = session.putAllAttributes(returnFlowfile, attributesToUpdate);
    }
    if (attributesToDelete.size() > 0) {
        returnFlowfile = session.removeAllAttributes(returnFlowfile, attributesToDelete);
    }
    return returnFlowfile;
}
Also used : Pattern(java.util.regex.Pattern) FlowFile(org.apache.nifi.flowfile.FlowFile) Action(org.apache.nifi.update.attributes.Action) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) URISyntaxException(java.net.URISyntaxException) ComponentLog(org.apache.nifi.logging.ComponentLog) URI(java.net.URI) URISyntaxException(java.net.URISyntaxException) ProcessException(org.apache.nifi.processor.exception.ProcessException) IOException(java.io.IOException) ProcessException(org.apache.nifi.processor.exception.ProcessException) Rule(org.apache.nifi.update.attributes.Rule) HashSet(java.util.HashSet)

Example 8 with Action

use of org.apache.nifi.update.attributes.Action in project nifi by apache.

the class UpdateAttribute method search.

@Override
public Collection<SearchResult> search(final SearchContext context) {
    final String term = context.getSearchTerm();
    final Collection<SearchResult> results = new ArrayList<>();
    if (StringUtils.isBlank(context.getAnnotationData())) {
        return results;
    }
    try {
        // parse the annotation data
        final Criteria criteria = CriteriaSerDe.deserialize(context.getAnnotationData());
        // ensure there are some rules
        if (criteria.getRules() != null) {
            final FlowFilePolicy flowFilePolicy = criteria.getFlowFilePolicy();
            if (flowFilePolicy != null && StringUtils.containsIgnoreCase(flowFilePolicy.name(), term)) {
                results.add(new SearchResult.Builder().label("FlowFile policy").match(flowFilePolicy.name()).build());
            }
            for (final Rule rule : criteria.getRules()) {
                if (StringUtils.containsIgnoreCase(rule.getName(), term)) {
                    results.add(new SearchResult.Builder().label("Rule name").match(rule.getName()).build());
                }
                // ensure there are some conditions
                if (rule.getConditions() != null) {
                    for (final Condition condition : rule.getConditions()) {
                        if (StringUtils.containsIgnoreCase(condition.getExpression(), term)) {
                            results.add(new SearchResult.Builder().label(String.format("Condition in rule '%s'", rule.getName())).match(condition.getExpression()).build());
                        }
                    }
                }
                // ensure there are some actions
                if (rule.getActions() != null) {
                    for (final Action action : rule.getActions()) {
                        if (StringUtils.containsIgnoreCase(action.getAttribute(), term)) {
                            results.add(new SearchResult.Builder().label(String.format("Action in rule '%s'", rule.getName())).match(action.getAttribute()).build());
                        }
                        if (StringUtils.containsIgnoreCase(action.getValue(), term)) {
                            results.add(new SearchResult.Builder().label(String.format("Action in rule '%s'", rule.getName())).match(action.getValue()).build());
                        }
                    }
                }
            }
        }
        return results;
    } catch (Exception e) {
        return results;
    }
}
Also used : Condition(org.apache.nifi.update.attributes.Condition) Action(org.apache.nifi.update.attributes.Action) FlowFilePolicy(org.apache.nifi.update.attributes.FlowFilePolicy) ArrayList(java.util.ArrayList) SearchResult(org.apache.nifi.search.SearchResult) Criteria(org.apache.nifi.update.attributes.Criteria) Rule(org.apache.nifi.update.attributes.Rule) URISyntaxException(java.net.URISyntaxException) ProcessException(org.apache.nifi.processor.exception.ProcessException) IOException(java.io.IOException)

Example 9 with Action

use of org.apache.nifi.update.attributes.Action in project nifi by apache.

the class UpdateAttribute method onScheduled.

@OnScheduled
public void onScheduled(final ProcessContext context) throws IOException {
    criteriaCache.set(CriteriaSerDe.deserialize(context.getAnnotationData()));
    propertyValues.clear();
    if (stateful) {
        StateManager stateManager = context.getStateManager();
        StateMap state = stateManager.getState(Scope.LOCAL);
        HashMap<String, String> tempMap = new HashMap<>();
        tempMap.putAll(state.toMap());
        String initValue = context.getProperty(STATEFUL_VARIABLES_INIT_VALUE).getValue();
        // Initialize the stateful default actions
        for (PropertyDescriptor entry : context.getProperties().keySet()) {
            if (entry.isDynamic()) {
                if (!tempMap.containsKey(entry.getName())) {
                    tempMap.put(entry.getName(), initValue);
                }
            }
        }
        // Initialize the stateful actions if the criteria exists
        final Criteria criteria = criteriaCache.get();
        if (criteria != null) {
            for (Rule rule : criteria.getRules()) {
                for (Action action : rule.getActions()) {
                    if (!tempMap.containsKey(action.getAttribute())) {
                        tempMap.put(action.getAttribute(), initValue);
                    }
                }
            }
        }
        context.getStateManager().setState(tempMap, Scope.LOCAL);
    }
    defaultActions = getDefaultActions(context.getProperties());
    debugEnabled = getLogger().isDebugEnabled();
}
Also used : Action(org.apache.nifi.update.attributes.Action) StateManager(org.apache.nifi.components.state.StateManager) PropertyDescriptor(org.apache.nifi.components.PropertyDescriptor) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) StateMap(org.apache.nifi.components.state.StateMap) Criteria(org.apache.nifi.update.attributes.Criteria) Rule(org.apache.nifi.update.attributes.Rule) OnScheduled(org.apache.nifi.annotation.lifecycle.OnScheduled)

Aggregations

Action (org.apache.nifi.update.attributes.Action)9 Rule (org.apache.nifi.update.attributes.Rule)6 Criteria (org.apache.nifi.update.attributes.Criteria)5 HashMap (java.util.HashMap)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)4 Condition (org.apache.nifi.update.attributes.Condition)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 StateMap (org.apache.nifi.components.state.StateMap)3 URISyntaxException (java.net.URISyntaxException)2 Map (java.util.Map)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2 Path (javax.ws.rs.Path)2 Produces (javax.ws.rs.Produces)2 WebApplicationException (javax.ws.rs.WebApplicationException)2 ResponseBuilder (javax.ws.rs.core.Response.ResponseBuilder)2 UriBuilder (javax.ws.rs.core.UriBuilder)2 PropertyDescriptor (org.apache.nifi.components.PropertyDescriptor)2 FlowFile (org.apache.nifi.flowfile.FlowFile)2 ComponentLog (org.apache.nifi.logging.ComponentLog)2