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

io.smallrye.graphql.schema.creator.ArgumentCreator Maven / Gradle / Ivy

The newest version!
package io.smallrye.graphql.schema.creator;

import java.util.List;
import java.util.Optional;

import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.logging.Logger;

import io.smallrye.graphql.schema.Annotations;
import io.smallrye.graphql.schema.SchemaBuilderException;
import io.smallrye.graphql.schema.helper.BeanValidationDirectivesHelper;
import io.smallrye.graphql.schema.helper.DeprecatedDirectivesHelper;
import io.smallrye.graphql.schema.helper.Direction;
import io.smallrye.graphql.schema.helper.IgnoreHelper;
import io.smallrye.graphql.schema.helper.MethodHelper;
import io.smallrye.graphql.schema.model.Argument;
import io.smallrye.graphql.schema.model.DirectiveInstance;
import io.smallrye.graphql.schema.model.Operation;
import io.smallrye.graphql.schema.model.Reference;
import io.smallrye.graphql.schema.model.ReferenceType;

/**
 * Creates a Argument object
 *
 * @author Phillip Kruger ([email protected])
 */
public class ArgumentCreator extends ModelCreator {

    private final BeanValidationDirectivesHelper validationHelper;
    private final DeprecatedDirectivesHelper deprecatedHelper;

    private final Logger logger = Logger.getLogger(ArgumentCreator.class.getName());

    public ArgumentCreator(ReferenceCreator referenceCreator) {
        super(referenceCreator);
        validationHelper = new BeanValidationDirectivesHelper();
        deprecatedHelper = new DeprecatedDirectivesHelper();
    }

    @Override
    public String getDirectiveLocation() {
        return "ARGUMENT_DEFINITION";
    }

    /**
     * Create an argument model. Arguments exist on Operations as input parameters
     *
     * @param operation The operation
     * @param methodInfo the operation method
     * @param position the argument position
     * @return an Argument
     */
    public Optional createArgument(Operation operation, MethodInfo methodInfo, short position) {
        if (position >= methodInfo.parametersCount()) {
            throw new SchemaBuilderException(
                    "Can not create argument for parameter [" + position + "] "
                            + "on method [" + methodInfo.declaringClass().name() + "#" + methodInfo.name() + "]: "
                            + "method has only " + methodInfo.parametersCount() + " parameters");
        }

        Annotations annotationsForThisArgument = Annotations.getAnnotationsForArgument(methodInfo, position);

        if (IgnoreHelper.shouldIgnore(annotationsForThisArgument)) {
            return Optional.empty();
        }

        // Argument Type
        Type argumentType = methodInfo.parameterType(position);

        // Name
        String defaultName = methodInfo.parameterName(position);
        String name = annotationsForThisArgument.getOneOfTheseAnnotationsValue(Annotations.NAME)
                .orElse(defaultName);

        Reference reference;
        if (isSourceAnnotationOnSourceOperation(annotationsForThisArgument, operation)) {
            reference = referenceCreator.createReferenceForSourceArgument(argumentType, annotationsForThisArgument);
        } else if (!argumentType.name().equals(CONTEXT)) {
            reference = referenceCreator.createReferenceForOperationArgument(argumentType, annotationsForThisArgument);
        } else {
            reference = CONTEXT_REF;
        }

        Argument argument = new Argument(defaultName,
                methodInfo.name(),
                MethodHelper.getPropertyName(Direction.IN, methodInfo.name()),
                name,
                reference);

        if (isSourceAnnotationOnSourceOperation(annotationsForThisArgument, operation)) {
            argument.setSourceArgument(true);
        }

        if (validationHelper != null) {
            List constraintDirectives = validationHelper
                    .transformBeanValidationConstraintsToDirectives(annotationsForThisArgument);
            if (!constraintDirectives.isEmpty()) {
                logger.debug("Adding constraint directives " + constraintDirectives + " to argument '" + argument.getName()
                        + "' of method '" + argument.getMethodName() + "'");
                argument.addDirectiveInstances(constraintDirectives);
            }
        }
        if (deprecatedHelper != null && directives != null) {
            deprecatedHelper
                    .transformDeprecatedToDirective(annotationsForThisArgument,
                            directives.getDirectiveTypes().get(DotName.createSimple("io.smallrye.graphql.api.Deprecated")))
                    .ifPresent(deprecatedDirective -> {
                        logger.debug(
                                "Adding deprecated directive " + deprecatedDirective + " to argument '"
                                        + argument.getName()
                                        + "' of method '" + argument.getMethodName() + "'");
                        argument.addDirectiveInstance(deprecatedDirective);
                    });
        }

        populateField(Direction.IN, argument, argumentType, annotationsForThisArgument);

        return Optional.of(argument);
    }

    /**
     * Source operation on types should remove the Source argument
     */
    private static boolean isSourceAnnotationOnSourceOperation(Annotations annotationsForArgument,
            Operation operation) {
        return operation.isSourceField() &&
                annotationsForArgument.containsOneOfTheseAnnotations(Annotations.SOURCE);
    }

    private static final DotName CONTEXT = DotName.createSimple("io.smallrye.graphql.api.Context");
    private static final Reference CONTEXT_REF = new Reference.Builder()
            .className(CONTEXT.toString())
            .name(CONTEXT.toString())
            .type(ReferenceType.TYPE)
            .build();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy