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

org.rapidgraphql.client.GraphQLRequestBuilder Maven / Gradle / Ivy

The newest version!
package org.rapidgraphql.client;

import org.rapidgraphql.annotations.GraphQLInputType;
import org.rapidgraphql.client.annotations.*;
import org.rapidgraphql.client.exceptions.RapidGraphQLQueryBuilderException;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.Map.entry;
import static org.rapidgraphql.client.TypeUtils.declareType;

public class GraphQLRequestBuilder {
    public static GraphQLRequestBody build(Method method, Object[] args) {
        GraphQLRequestBody request = initializeRequest(method);
        processMethodArguments(request, method, args);
        return request;
    }

    private static GraphQLRequestBody initializeRequest(Method method) {
        Optional request;
        request = Optional.ofNullable(method.getAnnotation(GraphQL.class))
                .map(graphQL -> initializeRequest(graphQL, method) );
        if (request.isPresent()) {
            return request.get();
        }
        request = Optional.ofNullable(method.getAnnotation(GraphQLQuery.class))
                .map(graphQLQuery -> initializeRequest(graphQLQuery, method) );
        if (request.isPresent()) {
            return request.get();
        }
        request = Optional.ofNullable(method.getAnnotation(GraphQLMutation.class))
                .map(graphQLMutation -> initializeRequest(graphQLMutation, method) );
        if (request.isPresent()) {
            return request.get();
        }
        throw new RuntimeException("No @GraphQL/@GraphQL annotation defined on method " + method.getName());
    }

    private static GraphQLRequestBody initializeRequest(GraphQLQuery graphQLQuery, Method method) {
        return initializeRequest("query", graphQLQuery.value(), method);
    }
    private static GraphQLRequestBody initializeRequest(GraphQLMutation graphQLQuery, Method method) {
        return initializeRequest("mutation", graphQLQuery.value(), method);
    }

    private static GraphQLRequestBody initializeRequest(String queryType, String query, Method method) {
        GraphQLRequestBody graphQLRequestBody = GraphQLRequestBody.builder()
                .fieldName(method.getName())
                .build();
        StringBuilder queryBuilder = new StringBuilder(queryType);
        queryBuilder.append(' ');
        queryBuilder.append(method.getName());
        addVariablesDeclaration(queryBuilder, method);
        queryBuilder.append('{');
        if (!(tryDefaultQueryOfSimpleType(query, method, queryBuilder) ||
              tryQueryOfObjectType(query, method, queryBuilder) ||
              tryCustomQuery(query, method, queryBuilder, graphQLRequestBody))) {
            throw new RapidGraphQLQueryBuilderException("Invalid query spacified in annotation");
        }
        queryBuilder.append('}');
        graphQLRequestBody.setQuery(queryBuilder.toString());
        return graphQLRequestBody;
    }

    private static final Pattern DEFAULT_QUERY = Pattern.compile("^\\s*\\{\\s*}\\s*$");
    private static final Predicate defaultQueryPredicate = DEFAULT_QUERY.asMatchPredicate();
    private static boolean tryDefaultQueryOfSimpleType(String query, Method method, StringBuilder queryBuilder) {
        if (!defaultQueryPredicate.test(query)) {
            return false;
        }
        queryBuilder.append(method.getName());
        addVariablesReference(queryBuilder, method);
        return true;
    }

    private static final Pattern OBJECT_TYPE_QUERY = Pattern.compile("^\\s*\\{\\s*(\\{.*})\\s*}\\s*$", Pattern.DOTALL);
    private static boolean tryQueryOfObjectType(String query, Method method, StringBuilder queryBuilder) {
        Matcher matcher = OBJECT_TYPE_QUERY.matcher(query);
        if (!matcher.matches()) {
            return false;
        }
        queryBuilder.append(method.getName());
        addVariablesReference(queryBuilder, method);
        queryBuilder.append(matcher.group(1));
        return true;
    }

    private static final Pattern CUSTOM_QUERY = Pattern.compile("^\\s*\\{\\s*(([a-zA-Z_]\\w*).*)\\s*}\\s*$", Pattern.DOTALL);
    private static boolean tryCustomQuery(String query, Method method, StringBuilder queryBuilder, GraphQLRequestBody graphQLRequestBody) {
        Matcher matcher = CUSTOM_QUERY.matcher(query);
        if (!matcher.matches()) {
            return false;
        }
        queryBuilder.append(matcher.group(1));
        graphQLRequestBody.setFieldName(matcher.group(2));
        return true;
    }

    private static void addVariablesDeclaration(StringBuilder queryBuilder, Method method) {
        if (method.getParameterCount() == 0) {
            return;
        }
        queryBuilder.append('(');
        queryBuilder.append(Arrays.stream(method.getParameters())
                .filter(GraphQLRequestBuilder::filterQueryParameters)
                .map(p -> String.format("$%s: %s", p.getName(), declareType(p.getAnnotatedType())))
                .collect(Collectors.joining(", ")));

        queryBuilder.append(')');
    }

    private static void addVariablesReference(StringBuilder queryBuilder, Method method) {
        if (method.getParameterCount() == 0) {
            return;
        }
        queryBuilder.append('(');
        queryBuilder.append(Arrays.stream(method.getParameters())
                .filter(GraphQLRequestBuilder::filterQueryParameters)
                .map(p -> String.format("%s: $%s", p.getName(), p.getName()))
                .collect(Collectors.joining(", ")));

        queryBuilder.append(')');
    }

    private static boolean filterQueryParameters(Parameter parameter) {
        return !parameter.isAnnotationPresent(HttpHeader.class) && !parameter.isAnnotationPresent(Bearer.class);
    }

    private static GraphQLRequestBody initializeRequest(GraphQL graphQL, Method method) {
        String fieldName = graphQL.fieldName();
        if (fieldName==null || fieldName.isEmpty()) {
            fieldName = method.getName();
        }
        return GraphQLRequestBody.builder().query(graphQL.query()).fieldName(fieldName).build();
    }

    private static void processMethodArguments(GraphQLRequestBody requestBody, Method method, Object[] args) {
        Map graphQLVariables = new HashMap<>();
        Parameter[] parameters = method.getParameters();
        for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy