com.fivefaces.structureclient.domain.StructureSchemaWorkflowScaffold 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
package com.fivefaces.structureclient.domain;
import com.fivefaces.structure.schema.FieldType;
import com.fivefaces.structure.schema.StructureFieldSchema;
import com.fivefaces.structure.schema.StructureSchema;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@RequiredArgsConstructor
public class StructureSchemaWorkflowScaffold {
public Map scaffold(StructureSchema def) throws Exception {
String[] roles = new String[]{"UNMANNED", "ADMIN", "PATIENT"};
String workflowSuffix = def.getType().substring(0, 1).toUpperCase() + def.getType().substring(1);
String validateCreateMethod = getValidateCreateMethod(workflowSuffix, def.getType(), roles, def.getFields());
String createMethod = getCreateMethod(workflowSuffix, def.getType(), def.getFields());
String validateUpdateMethod = getValidateUpdateMethod(workflowSuffix, def.getType(), roles, def.getFields());
String updateMethod = getUpdateMethod(workflowSuffix, def.getType(), def.getFields());
String validateDeleteMethod = getValidateDeleteMethod(workflowSuffix, roles);
String deleteMethod = getDeleteMethod(workflowSuffix, def.getType());
HashMap functions = new HashMap<>();
functions.put("validateCreate" + workflowSuffix, validateCreateMethod);
functions.put("create" + workflowSuffix, createMethod);
functions.put("validateUpdate" + workflowSuffix, validateUpdateMethod);
functions.put("update" + workflowSuffix, updateMethod);
functions.put("validateDelete" + workflowSuffix, validateDeleteMethod);
functions.put("delete" + workflowSuffix, deleteMethod);
return functions;
}
private String getSubString(String componentString, String identifier) {
String result = null;
if (componentString.contains(identifier)) {
result = componentString.substring(componentString.indexOf(identifier) + identifier.length());
final String quoteType = identifier.substring(identifier.length() - 1);
result = result.substring(0, result.indexOf(quoteType));
}
return result;
}
private String getCreateMethod(final String className,
final String tableName,
final Map fields) {
final String input = "{\n" +
" \"name\": \"create%s\",\n" +
" \"functionDefinition\": {\n" +
" \"Comment\": \"A description of my state machine\",\n" +
" \"StartAt\": \"Validate Create %s\",\n" +
" \"States\": {\n" +
" \"Validate Create %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"Resource\": \"arn:aws:states:::states:startExecution.sync\",\n" +
" \"Parameters\": {\n" +
" \"StateMachineArn\": \"arn:aws:states:ap-southeast-2:705130463218:stateMachine:${var.environment}_validateCreate%s\",\n" +
" \"Input\": {\n" +
" \"NeedCallback \": true,\n" +
" \"query.$\": \"$.query\",\n" +
" \"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$\": \"$$.Execution.Id\"\n" +
" }\n" +
" },\n" +
" \"Next\": \"Save %s\",\n" +
" \"ResultPath\": \"$.input.validateCreate%s\"\n" +
" },\n" +
" \"Save %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"ResultPath\": \"$.input.save%s\",\n" +
" \"Resource\": \"arn:aws:states:::apigateway:invoke\",\n" +
" \"Parameters\": {\n" +
" \"ApiEndpoint\": \"${var.structureEndpoint}\",\n" +
" \"Path\": \"/structure/insert\",\n" +
" \"Method\": \"POST\",\n" +
" \"Headers\": {\n" +
" \"Content-Type\": [\n" +
" \"application/json\"\n" +
" ]\n" +
" },\n" +
" \"RequestBody\": {\n" +
" \"username.$\": \"$.query.authorization.username\",\n" +
" \"type\": \"%s\",\n" +
" \"workflow\": \"create%s\",\n" +
" \"query\": {\n %s \n" +
" }\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
return String.format(input, className, className, className, className, className, className, className, className,
tableName, className, getInsertProperties(true, fields));
}
private String getInsertProperties(final boolean insert, Map fields) {
final StringBuilder result = new StringBuilder();
final StringBuilder associations = new StringBuilder("\t\t\t\"associations\": [");
final Boolean[] hasAssociations = new Boolean[]{false};
fields.forEach((key, value) -> {
if (!value.isAssociation()) {
result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
} else {
hasAssociations[0] = true;
if (insert) {
associations.append("\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"").append(value.getReferencedStructure()).append("\",\n\t\t\t\t\t\"id.$\": \"$.query.").append(key).append("\"\n\t\t\t\t},");
}
}
});
final String associationsString = associations.substring(0, associations.length() - 1) + "]";
if (insert && associationsString.length() > 25) {
result.append(associationsString);
return result.toString();
} else {
if (hasAssociations[0]) {
result.append("\t\t\t\"embeddedDelete.$\": \"$.query.embeddedDelete\",\n" +
"\t\t\t\"embeddedAdd.$\": \"$.query.embeddedAdd\"");
return result.toString();
}
if (result.length() > 0) {
return result.substring(0, result.length() - 2);
} else {
return result.toString();
}
}
}
private String getValidateCreateMethod(final String workflowSuffixName, final String tableName, final String[] rolesArray,
final Map fields) {
final String properties = getProperties(fields);
final String required = getRequiredProperties(fields, false);
final String unique = getUniqueProperties(fields);
final String roles = getArrayProperties(rolesArray);
final String input = "{\n" +
" \"name\": \"validateCreate%s\",\n" +
" \"functionDefinition\": {\n" +
" \"Comment\": \"Check the Users Roles\",\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" +
" \"type\": \"%s\",\n" +
" \"workflow\": \"validateCreate%s\",\n" +
" \"query.$\": \"$.query\",\n" +
" \"schema\": {\n" +
" \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" +
" \"title\": \"validateCreate%s\",\n" +
" \"description\": \"validateCreate%s\",\n" +
" \"type\": \"object\",\n" +
" \"properties\": {\n" +
"%s" +
"}\n" +
" },\n" +
" \"required\": [%s],\n" +
" \"unique\": [%s]\n" +
" }\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
return String.format(input, workflowSuffixName, roles, tableName, workflowSuffixName, workflowSuffixName, workflowSuffixName, properties, required, unique);
}
private String getValidateUpdateMethod(final String className, final String tableName, final String[] rolesArray,
final Map fields) {
final String properties = getProperties(fields);
final String required = getRequiredProperties(fields, true);
final String unique = getUniqueProperties(fields);
final String roles = getArrayProperties(rolesArray);
final String input = "{\n" +
" \"name\": \"validateUpdate%s\",\n" +
" \"functionDefinition\": {\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" +
" \"type\": \"%s\",\n" +
" \"updateId.$\": \"$.query.id\",\n" +
" \"workflow\": \"validateUpdate%s\",\n" +
" \"query.$\": \"$.query\",\n" +
" \"schema\": {\n" +
" \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" +
" \"title\": \"validateUpdate%s\",\n" +
" \"description\": \"validateUpdate%s\",\n" +
" \"type\": \"object\",\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"description\": \"id\",\n" +
" \"type\": \"string\",\"minLength\":1\n" +
" },\n" +
" \"version\": {\n" +
" \"description\": \"version\",\n" +
" \"type\": \"integer\"\n" +
" },\n" +
"%s\n" +
" }\n" +
" },\n" +
" \"required\": [%s],\n" +
" \"unique\": [%s]\n" +
" }\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
"}\n" +
"}";
return String.format(input, className, roles, tableName, className, className, className, properties, required, unique);
}
private String getUpdateMethod(final String className,
final String tableName,
final Map fields) {
final String input = "{\n" +
" \"name\": \"update%s\",\n" +
" \"functionDefinition\": {\n" +
" \"Comment\": \"A description of my state machine\",\n" +
" \"StartAt\": \"Validate Update %s\",\n" +
" \"States\": {\n" +
" \"Validate Update %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"Resource\": \"arn:aws:states:::states:startExecution.sync\",\n" +
" \"Parameters\": {\n" +
" \"StateMachineArn\": \"arn:aws:states:ap-southeast-2:705130463218:stateMachine:${var.environment}_validateUpdate%s\",\n" +
" \"Input\": {\n" +
" \"NeedCallback \": true,\n" +
" \"query.$\": \"$.query\",\n" +
" \"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$\": \"$$.Execution.Id\"\n" +
" }\n" +
" },\n" +
" \"Next\": \"Update %s\",\n" +
" \"ResultPath\": \"$.input.validateUpdate%s\"\n" +
" },\n" +
" \"Update %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"Resource\": \"arn:aws:states:::apigateway:invoke\",\n" +
" \"Parameters\": {\n" +
" \"ApiEndpoint\": \"${var.structureEndpoint}\",\n" +
" \"Path\": \"/structure/update\",\n" +
" \"Method\": \"POST\",\n" +
" \"Headers\": {\n" +
" \"Content-Type\": [\n" +
" \"application/json\"\n" +
" ]\n" +
" },\n" +
" \"RequestBody\": {\n" +
" \"username.$\": \"$.query.authorization.username\",\n" +
" \"type\": \"%s\",\n" +
" \"id.$\": \"$.query.id\",\n" +
" \"version.$\": \"$.query.version\",\n" +
" \"query\": {\n" +
" \"id.$\": \"$.query.id\",\n" +
"%s\n" +
" }\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
"}\n" +
"}";
return String.format(input, className, className, className, className, className, className, className,
tableName,
getInsertProperties(false, fields));
}
private String getValidateDeleteMethod(final String className, final String[] rolesArray) {
final String roles = getArrayProperties(rolesArray);
final String input = "{\n" +
" \"name\": \"validateDelete%s\",\n" +
" \"functionDefinition\": {\n" +
" \"Comment\": \"Validate Delete %s\",\n" +
" \"StartAt\": \"Check User Role\",\n" +
" \"States\": {\n" +
" \"Check User Role\": {\n" +
" \"Type\": \"Task\",\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" +
" \"ResultPath\": \"$.input.checkAuthorization\",\n" +
" \"Next\": \"Validate JSON\"\n" +
" },\n" +
" \"Validate JSON\": {\n" +
" \"Type\": \"Task\",\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\": \"validateDelete%s\",\n" +
" \"query.$\": \"$.query\",\n" +
" \"schema\": {\n" +
" \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" +
" \"title\": \"validateDelete%s\",\n" +
" \"description\": \"validateDelete%s\",\n" +
" \"type\": \"object\",\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"description\": \"id\",\n" +
" \"type\": \"string\",\"minLength\":1\n" +
" }\n" +
" },\n" +
" \"required\": [\n" +
" \"id\"\n" +
" ]\n" +
" }\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
return String.format(input, className, className, roles, className, className, className);
}
private String getDeleteMethod(final String className,
final String tableName) {
final String input = "{\n" +
" \"name\": \"delete%s\",\n" +
" \"functionDefinition\": {\n" +
" \"Comment\": \"Delete %s\",\n" +
" \"StartAt\": \"Validate Delete %s\",\n" +
" \"States\": {\n" +
" \"Validate Delete %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"Resource\": \"arn:aws:states:::states:startExecution.sync\",\n" +
" \"Parameters\": {\n" +
" \"StateMachineArn\": \"arn:aws:states:ap-southeast-2:705130463218:stateMachine:${var.environment}_validateDelete%s\",\n" +
" \"Input\": {\n" +
" \"NeedCallback \": true,\n" +
" \"query.$\": \"$.query\",\n" +
" \"AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$\": \"$$.Execution.Id\"\n" +
" }\n" +
" },\n" +
" \"Next\": \"Delete %s\",\n" +
" \"ResultPath\": \"$.input.validateDelete%s\"\n" +
" },\n" +
" \"Delete %s\": {\n" +
" \"Type\": \"Task\",\n" +
" \"Resource\": \"arn:aws:states:::apigateway:invoke\",\n" +
" \"Parameters\": {\n" +
" \"ApiEndpoint\": \"${var.structureEndpoint}\",\n" +
" \"Path\": \"/structure/delete\",\n" +
" \"Method\": \"POST\",\n" +
" \"Headers\": {\n" +
" \"Content-Type\": [\n" +
" \"application/json\"\n" +
" ]\n" +
" },\n" +
" \"RequestBody\": {\n" +
" \"type\": \"%s\",\n" +
" \"id.$\": \"$.query.id\",\n" +
" \"criteria\": [\n" +
" {\n" +
" \"member\": \"$.id\",\n" +
" \"type\": \"eq\",\n" +
" \"string\": true,\n" +
" \"value.$\": \"$.query.id\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"AuthType\": \"IAM_ROLE\"\n" +
" },\n" +
" \"End\": true\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
return String.format(input, className, className, className, className, className, className, className, className, tableName);
}
private String getProperties(Map fields) {
final StringBuilder result = new StringBuilder();
fields.forEach((key, value) -> {
if (value.getType().equals(FieldType.STRING)) {
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("string").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 (List.of(FieldType.DATETIME, FieldType.DATE, FieldType.TIME).contains(value.getType())) {
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().getJsonType()).append("\",\"format\": \"").append(value.getType().getJsonFormat()).append("\"");
result.append("\n\t\t\t\t},\n");
} else {
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().getJsonType()).append("\"");
result.append("\n\t\t\t\t},\n");
}
});
if (result.indexOf(",") >= 0) {
return result.substring(0, result.lastIndexOf(",") - 1);
} else {
return result.toString();
}
}
private String getRequiredProperties(Map fields,
final boolean update) {
final StringBuilder result = new StringBuilder();
fields.forEach((key, value) -> {
if (value.isRequired()) {
if (value.getType().equals(FieldType.STRING) && update && value.isAssociation()) {
// not adding associations to update as they will be done with embedded
} else {
result.append("\"").append(key).append("\",");
}
}
});
if (update) {
result.append("\"id\",");
}
if (result.indexOf(",") >= 0) {
return result.substring(0, result.length() - 1);
} else {
return result.toString();
}
}
private String getUniqueProperties(Map fields) {
final StringBuilder result = new StringBuilder();
fields.forEach((key, value) -> {
if (value.isUnique()) {
result.append("\"").append(key).append("\",");
}
});
if (result.length() > 0) {
return result.substring(0, result.length() - 1);
} else {
return "";
}
}
private String getArrayProperties(final String[] values) {
if (values.length == 0) {
return "";
}
final StringBuilder result = new StringBuilder();
for (String role : values) {
result.append("\"").append(role).append("\",");
}
return result.substring(0, result.length() - 1);
}
}