com.fivefaces.structureclient.service.statemachine.ScaffoldUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common-structure-client Show documentation
Show all versions of common-structure-client Show documentation
structure Client for Five Faces
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;
}
}