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

com.fivefaces.structureclient.service.statemachine.ScaffoldUtils Maven / Gradle / Ivy

The newest version!
package com.fivefaces.structureclient.service.statemachine;

import com.fivefaces.structure.schema.StructureDefinition;
import com.fivefaces.structure.schema.StructureFieldDefinition;
import com.fivefaces.structure.schema.StructureFieldType;
import com.fivefaces.structure.service.StructureDefinitionSchemaLoader;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
@RequiredArgsConstructor
public class ScaffoldUtils {

    private final StructureDefinitionSchemaLoader structureDefinitionSchemaLoader;

    public String getSubtaskStep(String stateMachine, String arn, Map subtaskParameters, String query, String next, String destination) {
        final String subTaskStep = String.format("  \"Type\": \"Task\",\n" +
                        "      \"Resource\": \"arn:aws:states:::states:startExecution.sync:2\",\n" +
                        "      \"ResultPath\": \"$.input.%s\",\n" +
                        "      \"Parameters\": {\n" +
                        "        \"StateMachineArn\": \"%s:stateMachine:${var.environment}_%s\",\n" +
                        "        \"Input\": {\n" +
                        "          \"NeedCallback \": true,\n" +
                        "          \"query\": {\n" +
                        "%s\n" +
                        "          },\n" +
                        "          \"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$\": \"$$.Execution.Id\"\n" +
                        "        }\n" +
                        "      },\n" +
                        "      %s",
                CaseUtils.toCamelCase(subtaskParameters.get("name"), false, ' '), arn, destination, query, next);
        final String replaceString = "***" + subtaskParameters.get("name") + "***";
        return stateMachine.replace(replaceString, subTaskStep);
    }

    public String getRoleNames(Map validateParameters) {
        String requiredRoleNames = validateParameters.get("roles");
        if (requiredRoleNames == null) {
            requiredRoleNames = "";
        }
        return requiredRoleNames;
    }


    public String getEntity(ScaffoldStateMachineResult result, Map subtaskParameters) {
        String query;
        final StringBuilder querys = getFieldParameters(result, subtaskParameters);
        query = querys + "            \"username.$\": \"$.query.authorization.username\",";
        return query;
    }

    public String addNextStep(ScaffoldStateMachineResult result, String[] lines, int counter, Map subtaskParameters) throws Exception {
        String next = "\"End\": true";
        if (subtaskParameters.containsKey("next")) {
            next = String.format("\"Next\": \"%s\"", subtaskParameters.get("next"));
            if (!getSteps(lines).contains(subtaskParameters.get("next"))) {
                result.getWarnings().add(String.format("Next value of %s is not valid for step %s", subtaskParameters.get("next"), subtaskParameters.get("name")));
            }

        } else {
            if (counter + 1 < lines.length) {
                next = String.format("\"Next\": \"%s\"", getStepName(lines[counter + 1]));
            }
        }
        return next;
    }

    public List getExclusions(Map validateParameters) {
        List exclusions = new ArrayList<>();
        validateParameters.keySet().stream().filter(s -> s.startsWith("exclude")).forEach(s -> {
            String[] parameters = validateParameters.get(s).split(" ");
            exclusions.addAll(Arrays.asList(parameters));
        });
        return exclusions;
    }

    public StringBuilder getFieldParameters(ScaffoldStateMachineResult result, Map subtaskParameters) {
        StructureDefinition schema = structureDefinitionSchemaLoader.getTargetDefinitions().get(subtaskParameters.get("entity"));
        Map fieldNames = new HashMap<>(schema.getFields());
        final StringBuilder querys = new StringBuilder();

        subtaskParameters.keySet().stream().filter(s -> s.startsWith("exclude")).forEach(s -> {
            String[] parameters = subtaskParameters.get(s).split(" ");
            if (parameters.length == 1) {
                final String field = parameters[0];
                fieldNames.remove(field);
                if (!schema.getFields().containsKey(field)) {
                    result.getWarnings().add(String.format("%s is not a valid exclusion for step %s", field, subtaskParameters.get("name")));
                }

            } else {
                Arrays.stream(parameters).forEach(field -> {
                    fieldNames.remove(field);
                    result.getWarnings().add(String.format("%s is not a valid exclusion for step %s", field, subtaskParameters.get("name")));
                });
            }
        });

        subtaskParameters.keySet().stream().filter(s -> s.startsWith("property")).forEach(s -> {
            String[] parameters = subtaskParameters.get(s).split(" ");
            final String field = parameters[0];

            // check if a straight parameter
            if (parameters.length == 1) {
                querys.append("            \"").append(field).append(".$\": \"$.query.").append(field).append("\",\n");
                fieldNames.remove(field);

                if (!schema.getFields().containsKey(field)) {
                    result.getWarnings().add(String.format("%s is not a valid property for step %s", field, subtaskParameters.get("name")));
                }

            } else {

                StringBuilder val = getChoiceParams(parameters);

                StructureFieldDefinition f = fieldNames.get(field);
                if (f == null) {
                    result.getWarnings().add(String.format("%s is not a valid property for step %s", field, subtaskParameters.get("name")));
                } else {
                    String dynamic = "";
                    if (val.toString().startsWith("$")) {
                        dynamic = ".$";
                    }
                    if (f.getType().equals(StructureFieldType.BOOLEAN)) {
                        if (val.toString().trim().equals("true") || val.toString().trim().equals("false")) {
                            querys.append("            \"").append(field).append(dynamic).append("\": ").append(val.toString().trim()).append(",\n");
                        } else {
                            result.getWarnings().add(String.format("Boolean value must be case sensitive true or false for step %s", subtaskParameters.get("name")));
                        }
                    } else {
                        querys.append("            \"").append(field).append(dynamic).append("\": \"").append(val.toString().trim()).append("\",\n");
                    }
                    fieldNames.remove(field);
                }
                if (!schema.getFields().containsKey(field)) {
                    result.getWarnings().add(String.format("%s is not a valid property for step %s", field, subtaskParameters.get("name")));
                }
            }
        });

        return querys;
    }

    public String getAllActionStepPlaceholders(String[] lines) throws Exception {
        final StringBuilder result = new StringBuilder();
        int counter = 0;
        for (String line : lines) {
            final String lineLowerCase = line.toLowerCase(Locale.ROOT);
            if (!lineLowerCase.startsWith("workflow") && !lineLowerCase.startsWith("#") && !lineLowerCase.startsWith("\t") && !lineLowerCase.replaceAll("\t", "").startsWith("-next")) {
                final String stepName = getStepName(line);
                result.append("\t\"").append(stepName).append("\": {\n");
                result.append("\t***").append(stepName).append("***\n");
                if (counter == lines.length - 1) {
                    result.append("\t}");
                } else {
                    result.append("\t},\n");
                }
            }
            counter++;
        }

        return result.toString();
    }

    public List getSteps(String[] lines) throws Exception {
        List result = new ArrayList<>();
        for (String line : lines) {
            final String lineLowerCase = line.toLowerCase(Locale.ROOT);
            if (!lineLowerCase.startsWith("workflow") && !lineLowerCase.startsWith("#")) {
                final String stepName = getStepName(line);
                result.add(stepName);
            }
        }
        return result;
    }

    public String getStepName(String line) throws Exception {
        String[] parameters = line.split("-");
        for (String parameter : parameters) {
            final String parameterLowerCase = parameter.toLowerCase(Locale.ROOT);
            if (parameterLowerCase.startsWith("name ")) {
                return parameter.substring("name ".length()).trim();
            }
        }

        throw new Exception(String.format("Can't find step name for line %s", line));

    }

    public Map getParameters(String line, String... parametersList) {
        final Map result = new HashMap<>();
        String[] parameters = line.split("-");
        for (String parameter : parameters) {
            for (String searchParameter : parametersList) {
                final String parameterLowerCase = parameter.toLowerCase(Locale.ROOT);
                if (parameterLowerCase.startsWith(searchParameter)) {
                    if (searchParameter.equals("choice")
                            || searchParameter.equals("property")
                            || searchParameter.equals("exclude")) {
                        result.put(searchParameter + UUID.randomUUID(), parameter.substring(searchParameter.length() + 1).trim());
                    } else {
                        result.put(searchParameter, parameter.substring(searchParameter.length() + 1).trim());
                    }
                }
            }
        }

        return result;

    }

    public String getProperties(final List exclusions,
                                StructureDefinition schema) {

        if (schema == null) return "";
        final StringBuilder result = new StringBuilder();

        schema.getFields().forEach((key, value) -> {
            if (exclusions.contains(key)) {
                return;
            }
            if (value.getType().equals(StructureFieldType.STRING) || value.getType().equals(StructureFieldType.OBJECT)) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(key).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.getType()).append("\"");
                if (StringUtils.isNotBlank(value.getMin())) {
                    result.append(",\"minLength\":").append(value.getMin());
                }
                if (StringUtils.isNotBlank(value.getMax())) {
                    result.append(",\"maxLength\":").append(value.getMax());
                }
                result.append("\n\t\t\t\t},\n");
            } else if (value.getType().equals(StructureFieldType.INTEGER)) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(key).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.getType()).append("\"");
                result.append("\n\t\t\t\t},\n");
            } else if (value.getType().equals(StructureFieldType.BOOLEAN)) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(key).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.getType()).append("\"");
                result.append("\n\t\t\t\t},\n");
            } else if (value.getType().equals(StructureFieldType.ARRAY)) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(key).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.getType()).append("\"");
                result.append("\n\t\t\t\t},\n");
            } else if (value.getType().equals(StructureFieldType.DATETIME)) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(key).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"string\",\"format\": \"date-time\"");
                result.append("\n\t\t\t\t},\n");
            }
        });

        if (result.lastIndexOf(",") >0) {
            return result.substring(0, result.lastIndexOf(",") - 1);
        }
        return result.toString();
    }

    public String getRequiredProperties(final List exclusions,
                                        StructureDefinition schema, boolean addId) {
        if (schema == null) return "";
        final StringBuilder result = new StringBuilder();
        schema.getFields().forEach((key, value) -> {
            if (value.isRequired() && !exclusions.contains(key)) {
                result.append("\"").append(key).append("\",");
            }
        });

        if (addId) {
            result.append("\"id\",");
        }

        if (result.length() > 0) {
            return result.substring(0, result.length() - 1);
        }
        return "";
    }

    public String[] getFormattedInputLines(final String definition) {
        String[] originalLines = definition.split("\n");
        List linesList = new LinkedList<>();
        for (String readline : originalLines) {
            if (readline.startsWith("\t") || readline.startsWith(" ")) {
                String l = linesList.remove(linesList.size() - 1);
                l += readline;
                linesList.add(l);
            } else {
                linesList.add(readline);
            }
        }

        String[] linesCopy = new String[linesList.size()];
        return linesList.toArray(linesCopy);
    }

    public String getValidateStateMachine(final String name, final String roles,
                                          StructureDefinition schema,
                                           final List exclusions) {

        final String properties = getProperties(exclusions, schema);
        final String required = getRequiredProperties(exclusions, schema, false);
        final String input = "{\n" +
                "  \"Comment\": \"A description of my state machine\",\n" +
                "  \"StartAt\": \"Check User Role\",\n" +
                "  \"States\": {\n" +
                "    \"Check User Role\": {\n" +
                "      \"Type\": \"Task\", \"ResultPath\": \"$.input.checkAuthorization\",\n" +
                "      \"Resource\": \"arn:aws:states:::apigateway:invoke\",\n" +
                "      \"Parameters\": {\n" +
                "        \"ApiEndpoint\": \"${var.structureEndpoint}\",\n" +
                "        \"Path\": \"/structure/hasAnyRole\",\n" +
                "        \"Method\": \"POST\",\n" +
                "        \"Headers\": {\n" +
                "          \"Content-Type\": [\n" +
                "            \"application/json\"\n" +
                "          ]\n" +
                "        },\n" +
                "        \"RequestBody\": {\n" +
                "           \"requiredRoles\": [\n" +
                "             %s\n" +
                "           ],\n" +
                "           \"userRoles.$\": \"$.query.authorization.roles\"\n" +
                "         },\n" +
                "         \"AuthType\": \"IAM_ROLE\"\n" +
                "      },\n" +
                "      \"Next\": \"Validate JSON\"\n" +
                "    },\n" +
                "    \"Validate JSON\": {\n" +
                "      \"Type\": \"Task\", \"ResultPath\": \"$.input.validateJson\",\n" +
                "      \"Resource\": \"arn:aws:states:::apigateway:invoke\",\n" +
                "      \"Parameters\": {\n" +
                "        \"ApiEndpoint\": \"${var.structureEndpoint}\",\n" +
                "        \"Method\": \"POST\",\n" +
                "        \"Path\": \"/structure/validate\",\n" +
                "        \"Headers\": {\n" +
                "          \"Content-Type\": [\n" +
                "            \"application/json\"\n" +
                "          ]\n" +
                "        },\n" +
                "        \"RequestBody\": {\n" +
                "          \"workflow\": \"%s\",\n" +
                "          \"query.$\": \"$.query\",\n" +
                "          \"schema\": {\n" +
                "            \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" +
                "            \"title\": \"%s\",\n" +
                "            \"description\": \"%s\",\n" +
                "            \"type\": \"object\",\n" +
                "              \"properties\": {\n" +
                "%s\n" +
                "              }\n" +
                "            },\n" +
                "            \"required\": [%s]\n" +
                "          }\n" +
                "        },\n" +
                "        \"AuthType\": \"IAM_ROLE\"\n" +
                "      },\n" +
                "      \"End\": true\n" +
                "    }\n" +
                "  }\n" +
                "}";

        return String.format(input, roles, name, name, name, properties, required);
    }

    public StringBuilder getChoiceParams(String[] parameters) {
        final StringBuilder choiceParametersSB = new StringBuilder();
        for (int i = 1; i < parameters.length; i++) {
            choiceParametersSB.append(parameters[i]);
        }

        final StringBuilder val = new StringBuilder();
        if (choiceParametersSB.toString().contains("[")) {
            String fieldName = choiceParametersSB.substring(0, choiceParametersSB.indexOf("["));
            fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
            String fieldValue = choiceParametersSB.substring(choiceParametersSB.indexOf("[") + 1, choiceParametersSB.length() - 1);
            val.append("$.input.").append(fieldName).append(".ResponseBody[0].").append(fieldValue);
        } else {
            int c = 0;
            for (String parameter : parameters) {
                if (c > 0) {
                    val.append(parameter).append(" ");
                }
                c++;
            }
            if (val.toString().trim().equalsIgnoreCase("empty")) {
                val.setLength(0);
            }
        }
        return val;
    }




}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy