All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.validation.rules.ValidationRules Maven / Gradle / Ivy

package graphql.validation.rules;

import graphql.GraphQLError;
import graphql.PublicApi;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLFieldsContainer;
import graphql.validation.constraints.DirectiveConstraints;
import graphql.validation.interpolation.MessageInterpolator;
import graphql.validation.interpolation.ResourceBundleMessageInterpolator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import static graphql.Assert.assertNotNull;

/**
 * {@link ValidationRules} is a holder of validation rules
 * and you can then pass it field and arguments and narrow down the list of actual rules
 * that apply to those fields and arguments.
 * 

* It also allows you to run the appropriate rules via the * {@link #runValidationRules(graphql.schema.DataFetchingEnvironment)} method. */ @PublicApi public class ValidationRules { private final OnValidationErrorStrategy onValidationErrorStrategy; private final List rules; private final MessageInterpolator messageInterpolator; private final Locale locale; private ValidationRules(Builder builder) { this.rules = Collections.unmodifiableList(builder.rules); this.messageInterpolator = builder.messageInterpolator; this.onValidationErrorStrategy = builder.onValidationErrorStrategy; this.locale = builder.locale; } public MessageInterpolator getMessageInterpolator() { return messageInterpolator; } public Locale getLocale() { return locale; } public List getRules() { return rules; } public OnValidationErrorStrategy getOnValidationErrorStrategy() { return onValidationErrorStrategy; } public TargetedValidationRules buildRulesFor(GraphQLFieldDefinition fieldDefinition, GraphQLFieldsContainer fieldsContainer) { TargetedValidationRules.Builder rulesBuilder = TargetedValidationRules.newValidationRules(); ValidationCoordinates fieldCoordinates = ValidationCoordinates.newCoordinates(fieldsContainer, fieldDefinition); List fieldRules = getRulesFor(fieldDefinition, fieldsContainer); rulesBuilder.addRules(fieldCoordinates, fieldRules); for (GraphQLArgument fieldArg : fieldDefinition.getArguments()) { ValidationCoordinates validationCoordinates = ValidationCoordinates.newCoordinates(fieldsContainer, fieldDefinition, fieldArg); List rules = getRulesFor(fieldArg, fieldDefinition, fieldsContainer); rulesBuilder.addRules(validationCoordinates, rules); } return rulesBuilder.build(); } public List getRulesFor(GraphQLArgument fieldArg, GraphQLFieldDefinition fieldDefinition, GraphQLFieldsContainer fieldsContainer) { return rules.stream() .filter(rule -> rule.appliesTo(fieldArg, fieldDefinition, fieldsContainer)) .collect(Collectors.toList()); } public List getRulesFor(GraphQLFieldDefinition fieldDefinition, GraphQLFieldsContainer fieldsContainer) { return rules.stream() .filter(rule -> rule.appliesTo(fieldDefinition, fieldsContainer)) .collect(Collectors.toList()); } /** * This helper method will run the validation rules that apply to the provided {@link graphql.schema.DataFetchingEnvironment} * * @param env the data fetching environment * * @return a list of zero or more input data validation errors */ public List runValidationRules(DataFetchingEnvironment env) { GraphQLFieldsContainer fieldsContainer = env.getExecutionStepInfo().getFieldContainer(); GraphQLFieldDefinition fieldDefinition = env.getFieldDefinition(); MessageInterpolator messageInterpolator = this.getMessageInterpolator(); TargetedValidationRules rules = this.buildRulesFor(fieldDefinition, fieldsContainer); return rules.runValidationRules(env, messageInterpolator, this.getLocale()); } /** * A builder of validation rules. By default the SDL @directive rules from * {@link graphql.validation.constraints.DirectiveConstraints#STANDARD_CONSTRAINTS} are included * but you can add extra rules or call {@link graphql.validation.rules.ValidationRules.Builder#clearRules()} * to start afresh. * * @return a new builder of rules */ public static Builder newValidationRules() { return new Builder(); } public static class Builder { private Locale locale; private OnValidationErrorStrategy onValidationErrorStrategy = OnValidationErrorStrategy.RETURN_NULL; private MessageInterpolator messageInterpolator = new ResourceBundleMessageInterpolator(); private List rules = new ArrayList<>(); public Builder() { // we start with the standard directive constraints to make us easier to use addRules(DirectiveConstraints.STANDARD_CONSTRAINTS); } public Builder addRule(ValidationRule rule) { rules.add(assertNotNull(rule)); return this; } public Builder addRules(Collection rules) { rules.forEach(this::addRule); return this; } public Builder addRules(ValidationRule... rules) { return addRules(Arrays.asList(rules)); } public Builder clearRules() { rules.clear(); return this; } public Builder messageInterpolator(MessageInterpolator messageInterpolator) { this.messageInterpolator = assertNotNull(messageInterpolator); return this; } /** * This sets the locale of the validation rules. This is only needed while graphql-java does not allow you to get the * locale from the {@link graphql.ExecutionInput}. A PR for this is in the works. Once that is available, then this method * will not be as useful. * * @param locale the locale to use for message interpolation * * @return this builder */ public Builder locale(Locale locale) { this.locale = locale; return this; } public Builder onValidationErrorStrategy(OnValidationErrorStrategy onValidationErrorStrategy) { this.onValidationErrorStrategy = assertNotNull(onValidationErrorStrategy); return this; } public ValidationRules build() { return new ValidationRules(this); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy