<commit_before>package net.nemerosa.ontrack.boot.graphql;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import net.nemerosa.ontrack.json.ObjectMapperFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

@RestController
@RequestMapping("/graphql")
public class GraphqlController {

    private final GraphQLSchema schema;

    private final ObjectMapper objectMapper = ObjectMapperFactory.create();

    @Autowired
    public GraphqlController(GraphQLSchema schema) {
        this.schema = schema;
    }

    /**
     * GET end point
     */
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<JsonNode> get(
            @RequestParam String query,
            @RequestParam(required = false) String variables,
            @RequestParam(required = false) String operationName
    ) throws IOException {
        // Parses the arguments
        Map<String, Object> arguments = decodeIntoMap(variables);
        // Runs the query
        // TODO Execution strategy
        ExecutionResult executionResult = new GraphQL(schema).execute(query, operationName, null, arguments);
        // As JSON
        return ResponseEntity.ok(
                objectMapper.valueToTree(executionResult)
        );
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> decodeIntoMap(String variablesParam) throws IOException {
        if (StringUtils.isNotBlank(variablesParam)) {
            return objectMapper.readValue(variablesParam, Map.class);
        } else {
            return Collections.emptyMap();
        }
    }

}<commit_msg>#458 GraphQL controller - post<commit_after>package net.nemerosa.ontrack.boot.graphql;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import lombok.Data;
import lombok.experimental.Wither;
import net.nemerosa.ontrack.json.ObjectMapperFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

@RestController
@RequestMapping("/graphql")
public class GraphqlController {

    private final GraphQLSchema schema;

    private final ObjectMapper objectMapper = ObjectMapperFactory.create();

    @Autowired
    public GraphqlController(GraphQLSchema schema) {
        this.schema = schema;
    }

    /**
     * Request model
     */
    @Data
    public static class Request {
        private final String query;
        @Wither
        private final Map<String, Object> variables;
        private final String operationName;

        public Request withVariables() {
            if (variables == null) {
                return withVariables(Collections.emptyMap());
            } else {
                return this;
            }
        }
    }

    /**
     * GET end point
     */
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<JsonNode> get(
            @RequestParam String query,
            @RequestParam(required = false) String variables,
            @RequestParam(required = false) String operationName
    ) throws IOException {
        // Parses the arguments
        Map<String, Object> arguments = decodeIntoMap(variables);
        // Runs the query
        return ResponseEntity.ok(
                requestAsJson(
                        new Request(
                                query,
                                arguments,
                                operationName
                        )
                )
        );
    }

    /**
     * POST end point
     */
    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<JsonNode> post(@RequestBody String input) throws IOException {
        // Gets the components
        Request request = objectMapper.readValue(input, Request.class);
        // Variables must not be null
        request = request.withVariables();
        // Runs the query
        return ResponseEntity.ok(
                requestAsJson(request)
        );
    }

    /**
     * Request execution (JSON)
     */
    public JsonNode requestAsJson(Request request) {
        return objectMapper.valueToTree(
                request(request)
        );

    }

    /**
     * Request execution
     */
    public ExecutionResult request(Request request) {
        // TODO Execution strategy
        return new GraphQL(schema).execute(
                request.getQuery(),
                request.getOperationName(),
                null, // No context
                request.getVariables());

    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> decodeIntoMap(String variablesParam) throws IOException {
        if (StringUtils.isNotBlank(variablesParam)) {
            return objectMapper.readValue(variablesParam, Map.class);
        } else {
            return Collections.emptyMap();
        }
    }

}
{'fraction_non_alphanumeric': 0.08664898320070734, 'fraction_numerical': 0.0008841732979664014, 'mean_word_length': 2.52398753894081, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2147359', 'n_tokens_mistral': 1440, 'n_tokens_neox': 1390, 'n_words': 318}