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

com.fivefaces.structureclient.domain.Scaffold Maven / Gradle / Ivy

There is a newer version: 1.0.62
Show newest version
package com.fivefaces.structureclient.domain;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class Scaffold {

    public static void main(String[] args) throws Exception {
        Scaffold scaffold = new Scaffold();
        scaffold.scaffoldBDD();
    }

    public void scaffold(Class utilsClass) throws Exception {
        StructureDefinition def = new StructureDefinition(utilsClass);

        String classname = utilsClass.getDeclaredClasses()[0].getSimpleName();
        if (!def.getTableName().isEmpty()) {
            String validateCreateMethod = getValidateCreateMethod(classname, def.getTableName(), def.getRequiredRoleNames(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
            Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_validate_create_%s.tf", classname.toLowerCase(Locale.ROOT))), validateCreateMethod, StandardCharsets.UTF_8);
            String createMethod = getCreateMethod(classname, def.getTableName(), def.isWarehouse(), def.getInsertText(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
            Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_create_%s.tf", classname.toLowerCase(Locale.ROOT))), createMethod, StandardCharsets.UTF_8);

            if (def.isCreateUpdate()) {
                String validateUpdateMethod = getValidateUpdateMethod(classname, def.getTableName(), def.getRequiredRoleNames(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
                Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_validate_update_%s.tf", classname.toLowerCase(Locale.ROOT))), validateUpdateMethod, StandardCharsets.UTF_8);
                String updateMethod = getUpdateMethod(classname, def.getTableName(), def.isWarehouse(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
                Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_update_%s.tf", classname.toLowerCase(Locale.ROOT))), updateMethod, StandardCharsets.UTF_8);
            }
            String validateDeleteMethod = getValidateDeleteMethod(classname, def.getRequiredRoleNames());
            Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_validate_delete_%s.tf", classname.toLowerCase(Locale.ROOT))), validateDeleteMethod, StandardCharsets.UTF_8);
            String deleteMethod = getDeleteMethod(classname, def.getTableName(), def.isWarehouse());
            Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_delete_%s.tf", classname.toLowerCase(Locale.ROOT))), deleteMethod, StandardCharsets.UTF_8);

            Files.createDirectories(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s", classname.toLowerCase(Locale.ROOT))));
            Files.createDirectories(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s", classname.toLowerCase(Locale.ROOT))));
            String createTest = getCreateTest(classname, def.getRequiredRoleNames(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s/Create%sTest.java", classname.toLowerCase(Locale.ROOT), classname)), createTest, StandardCharsets.UTF_8);
            String updateTest = getUpdateTest(utilsClass.getDeclaredClasses()[0].getSimpleName(), def.getTableName(), def.getRequiredRoleNames(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s/Update%sTest.java", classname.toLowerCase(Locale.ROOT), classname)), updateTest, StandardCharsets.UTF_8);
            String deleteTest = getDeleteTest(utilsClass.getDeclaredClasses()[0].getSimpleName(), def.getTableName(), def.getRequiredRoleNames());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s/Delete%sTest.java", classname.toLowerCase(Locale.ROOT), classname)), deleteTest, StandardCharsets.UTF_8);
            String createAWSOnPremTest = getCreateAWSOnPremTest(utilsClass.getDeclaredClasses()[0].getSimpleName());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s/AWSOnPremiseCreate%sTest.java", classname.toLowerCase(Locale.ROOT), classname)),
                    createAWSOnPremTest, StandardCharsets.UTF_8);
            String updateAWSOnPremTest = getUpdateAWSOnPremTest(utilsClass.getDeclaredClasses()[0].getSimpleName());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s/AWSOnPremiseUpdate%sTest.java", classname.toLowerCase(Locale.ROOT), classname)),
                    updateAWSOnPremTest, StandardCharsets.UTF_8);
            String deleteAWSOnPremTest = getDeleteAWSOnPremTest(utilsClass.getDeclaredClasses()[0].getSimpleName());
            Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s/AWSOnPremiseDelete%sTest.java", classname.toLowerCase(Locale.ROOT), classname)),
                    deleteAWSOnPremTest, StandardCharsets.UTF_8);

            System.out.println("#DROP TABLE if exists `" + def.getTableName() + "`;\n\n");
            System.out.println("CREATE TABLE `" + def.getTableName() + "` (\n" +
                    "  `version` int NOT NULL AUTO_INCREMENT,\n" +
                    "  `id` varchar(36) NOT NULL,\n" +
                    "  `json_data` json DEFAULT NULL,\n" +
                    "  `created_at_utc` datetime DEFAULT NULL,\n" +
                    "  `created_by` varchar(45) DEFAULT NULL,\n" +
                    "  `last_modified_at_utc` datetime DEFAULT NULL,\n" +
                    "  `last_modified_by` varchar(45) DEFAULT NULL,\n" +
                    "  PRIMARY KEY (`version`,`id`)\n" +
                    ") ENGINE=InnoDB AUTO_INCREMENT=8588 DEFAULT CHARSET=latin1;\n\n");

            if (def.isWarehouse()) {
                System.out.println("#DROP TABLE if exists `" + def.getWarehouseSchema() + "`.`" + def.getTableName() + "`;\n\n");
                System.out.println(createWarehouseTable(def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields(), def.getWarehouseSchema(), def.getTableName()));
            }

            System.out.println(getIndexProperties(def.getTableName(), def.getWarehouseSchema(), def.getStringFields(), def.getIntegerFields()));
        } else {
            String validateCallMethod = getValidateCallMethod(classname, def.getCallName(), def.getRequiredRoleNames(), def.getStringFields(), def.getIntegerFields(), def.getBooleanFields(), def.getArrayFields(), def.getDateTimeFields());
            Files.writeString(Paths.get(String.format("src/main/resources/functions/sf_validate_%s.tf", def.getCallName().toLowerCase(Locale.ROOT))), validateCallMethod, StandardCharsets.UTF_8);
            Files.createDirectories(Paths.get("src/test/java/com/fivefaces/structuredpjapi/state/integration/calls"));
            Files.createDirectories(Paths.get("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/calls"));
            if (!Files.exists(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/calls/Call%sTest.java", classname.toLowerCase(Locale.ROOT))))) {
                String callTest = getCallTest(classname, def.getCallName());
                Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/calls/Call%sTest.java", classname)), callTest, StandardCharsets.UTF_8);
                String callAWSOnPremTest = getCallAWSOnPremTest(utilsClass.getDeclaredClasses()[0].getSimpleName());
                Files.writeString(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/calls/AWSOnPremiseCall%sTest.java", classname)), callAWSOnPremTest, StandardCharsets.UTF_8);
            }
        }
    }

    public void tearDown(Class utilsClass) throws Exception {

        String classname = utilsClass.getDeclaredClasses()[0].getSimpleName();
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_validate_create_%s.tf", classname.toLowerCase(Locale.ROOT))));
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_create_%s.tf", classname.toLowerCase(Locale.ROOT))));
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_validate_update_%s.tf", classname.toLowerCase(Locale.ROOT))));
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_update_%s.tf", classname.toLowerCase(Locale.ROOT))));
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_validate_delete_%s.tf", classname.toLowerCase(Locale.ROOT))));
        Files.deleteIfExists(Paths.get(String.format("src/main/resources/functions/sf_delete_%s.tf", classname.toLowerCase(Locale.ROOT))));

        try {
            Files.walk(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s", classname.toLowerCase(Locale.ROOT))))
                    .map(Path::toFile)
                    .forEach(File::delete);
        } catch (Exception ignore){};

        Files.deleteIfExists(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/%s", classname.toLowerCase(Locale.ROOT))));

        try {
        Files.walk(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s", classname.toLowerCase(Locale.ROOT))))
                .map(Path::toFile)
                .forEach(File::delete);
        } catch (Exception ignore){};

        Files.deleteIfExists(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/integration/awsonprem/%s", classname.toLowerCase(Locale.ROOT))));

        Files.deleteIfExists(Paths.get(String.format("src/test/java/com/fivefaces/structuredpjapi/state/createtable/Create%sWarehouseTest.java", classname)));
    }

    public void scaffoldBDD() throws IOException {
        final StringBuilder pythonFunctions = new StringBuilder();
        final StringBuilder steps = new StringBuilder();
        try {
            Files.walk(Paths.get("/Users/fivefaces/dev/replatform-ui/src/pages"))
                    .map(Path::toFile)
                    .filter(file -> file.getName().endsWith(".tsx")
                            && !file.getName().endsWith(".test.tsx")
                            && !file.getName().equals("index.tsx")
                            && !file.getName().equals("PermitedRoute.tsx")
                            && !file.getName().equals("FilterComponent.tsx")
                            && !file.getName().equals("AntdDataTable.tsx")
                            && !file.getName().equals("CRUDDataTable.tsx")
                            && !file.getName().equals("MsAuthPage.tsx"))
                    .forEach(f -> {
                        try {
                            System.out.println(f.getName());
                            processBDD(f, pythonFunctions, steps);
                            pythonFunctions.append("\n");
                            steps.append("\n");
                        } catch (Exception exception) {
                            try {
                                throw exception;
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
        } catch (Exception ignore){
            ignore.printStackTrace();
        };
        Files.createDirectories(Paths.get("src/main/resources/bdd"));
        Files.writeString(Paths.get("src/main/resources/bdd/pythonFunctions.txt"), pythonFunctions, StandardCharsets.UTF_8);
        Files.writeString(Paths.get("src/main/resources/bdd/stepFunctions.txt"), steps, StandardCharsets.UTF_8);

    }

    public static final String TEXTAREA = " inputIds = new HashSet<>();
        final Set selectionIds = new HashSet<>();
        final Set buttonIds = new HashSet<>();

        Arrays.stream(inputStrings).forEach(s -> {
            extracted(f, component, inputIds, s);
        });
        Arrays.stream(selectionStrings).forEach(s -> {
            extracted(f, component, selectionIds, s);
        });
        Arrays.stream(buttonStrings).forEach(s -> {
            extracted(f, component, buttonIds, s);
        });

        final Set allInputIds = new HashSet<>();
        allInputIds.addAll(inputIds);
        allInputIds.addAll(selectionIds);

        final StringBuilder sb = new StringBuilder();
        if (!allInputIds.isEmpty()) {
            String fields = String.join(", ", allInputIds);
            sb.append(String.format("def inform_%s(self, %s):\n", fileName.toLowerCase(Locale.ROOT), fields));

            inputIds.forEach(s -> {
                sb.append("\n");
                sb.append(String.format("    if %s is not None:\n", s));
                sb.append(String.format("        selection = self.locate_element_by_id_send_keys(\"%s\")\n", s));
                sb.append(String.format("        selection.send_keys(%s)\n", s));
                sb.append(String.format("        print(\"%s\" + \" found and \" + %s + \" entered!\")\n", s, s));
                sb.append("    else:\n");
                sb.append(String.format("        print(\"%s ignored because no value was sent to populate\")\n", s));
            });

            selectionIds.forEach(s -> {
                sb.append("\n");
                sb.append(String.format("    if %s is not None:\n", s));
                sb.append(String.format("        selection = self.locate_element_by_id_send_keys(\"%s\")\n", s));
                sb.append(String.format("        selection.send_keys(%s)\n", s));
                sb.append("        selection.send_keys(Keys.DOWN)\n");
                sb.append("        selection.send_keys(Keys.ENTER)\n");
                sb.append(String.format("        print(\"%s\" + \" found and \" + %s + \" entered!\")\n", s, s));
                sb.append("    else:\n");
                sb.append(String.format("        print(\"%s ignored because no value was sent to populate\")\n", s));
            });
        }

        buttonIds.forEach(s -> {
            sb.append(String.format("\n\ndef inform_click_%s(self):\n",s));
            sb.append(String.format("    selection = self.locate_element_by_id_send_keys(\"%s\")\n", s));
            sb.append("    selection.click()\n");
            sb.append(String.format("    print(\"%s found and clicked\")\n", s));
        });

        pythonFunctions.append(sb);

        final StringBuilder stepsSB = new StringBuilder();
        if (!allInputIds.isEmpty()) {
            final StringBuilder fields = new StringBuilder();
            allInputIds.forEach(s -> {
                fields.append("\"{").append(s).append("}\",");
            });
            stepsSB.append(String.format("@step('I populate component %s with values %s')\n", fileName.toLowerCase(Locale.ROOT), fields.substring(0, fields.length()-1)));
            stepsSB.append(String.format("def step_impl(context, %s):\n", String.join(", ", allInputIds)));
            stepsSB.append(String.format("    webapp.inform_%s(%s)\n", fileName.toLowerCase(Locale.ROOT), String.join(", ", allInputIds)));
        }

        buttonIds.forEach(s -> {
            stepsSB.append(String.format("\n@step('I select the %s button on component %s')\n", s, fileName.toLowerCase(Locale.ROOT)));
            stepsSB.append("def step_impl(context):\n");
            stepsSB.append(String.format("    webapp.inform_click_%s()\n", s));
        });

        steps.append(stepsSB);

    }

    private void extracted(File f, String component, Set idsList, String s) {
        String componentText = component;
        while (componentText.contains(s)) {
            try {
                componentText = componentText.substring(componentText.indexOf(s) + s.length());
                int closingIndex = componentText.indexOf("/>");
                if (closingIndex == -1) {
                    closingIndex = componentText.indexOf(">");
                }
                final String comparisionText = componentText.substring(0, closingIndex);
                final String id = getId(f.getName(), comparisionText);
                if (id != null) {
                    idsList.add(id);
                }
            } catch (Exception e) {
                e.getMessage();
            }
        }
    }

    private String getId(final String fileName, final String componentString) {

        String result;
        result = getSubString(componentString, "id=\"");
        if (result == null) {
            result = getSubString(componentString, "id='");
        }
        if (result == null) {
            result = getSubString(componentString, "id =\"");
        }
        if (result == null) {
            result = getSubString(componentString, "id ='");
        }
        if (result == null) {
            result = getSubString(componentString, "id = \"");
        }
        if (result == null) {
            result = getSubString(componentString, "id = '");
        }
        if (result == null) {
            result = getSubString(componentString, "id={\"");
        }

        if (result == null) {
            System.out.println("**************** " + fileName + " has missing id " + componentString);
        }
        return result;
    }

    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 getSteps(Map stringFields,
                            Map integerFields,
                            Map booleanFields,
                            Map arrayFields,
                            Map dateTimeFields) {

        final StringBuilder result = new StringBuilder();

        stringFields.forEach((key, value) -> {
            String stepValue;
            if (value != null) {
                if (key.endsWith("Id")) {
                    result.append("\t\tadd(stepPayload, \"").append(key).append("\",UUID.randomUUID()").append(");\n");
                } else {
                    stepValue = key + "_val";
                    result.append("\t\tadd(stepPayload, \"").append(key).append("\",\"").append(stepValue).append("\"  + UUID.randomUUID());\n");
                }

            }
        });

        integerFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\tadd(stepPayload, \"").append(key).append("\",").append("1").append(");\n");
            }
        });

        booleanFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\tadd(stepPayload, \"").append(key).append("\", true);\n");
            }
        });

        arrayFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\tadd(stepPayload, \"").append(key).append("\", new JSONArray());\n");
            }
        });

        dateTimeFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\tadd(stepPayload, \"").append(key).append("\",\"2018-06-08T04:54:47.731Z\");\n");
            }
        });

        return result.toString();
    }

    private Map getRequiredStrings(final Map stringFields, final boolean update) {
        Map required = new LinkedHashMap<>();

        for (Map.Entry stringFieldEntry : stringFields.entrySet()) {
            if (stringFieldEntry.getValue().required()) {
                required.put(stringFieldEntry.getKey(), stringFieldEntry.getValue());
            }
        }
        if (update) {
            required.put("id", null);
        }

        return required;
    }

    private Map getRequiredIntegers(final Map stringFields) {
        Map required = new LinkedHashMap<>();

        for (Map.Entry stringFieldEntry : stringFields.entrySet()) {
            if (stringFieldEntry.getValue().required()) {
                required.put(stringFieldEntry.getKey(), stringFieldEntry.getValue());
            }
        }

        return required;
    }

    private Map getRequiredBooleans(final Map stringFields) {
        Map required = new LinkedHashMap<>();

        for (Map.Entry stringFieldEntry : stringFields.entrySet()) {
            if (stringFieldEntry.getValue().required()) {
                required.put(stringFieldEntry.getKey(), stringFieldEntry.getValue());
            }
        }

        return required;
    }

    private Map getRequiredArrays(final Map stringFields) {
        Map required = new LinkedHashMap<>();

        for (Map.Entry stringFieldEntry : stringFields.entrySet()) {
            if (stringFieldEntry.getValue().required()) {
                required.put(stringFieldEntry.getKey(), stringFieldEntry.getValue());
            }
        }

        return required;
    }

    private Map getRequiredDateTimes(final Map DateTimeField) {
        Map required = new LinkedHashMap<>();

        for (Map.Entry dateTimeFieldEntry : DateTimeField.entrySet()) {
            if (dateTimeFieldEntry.getValue().required()) {
                required.put(dateTimeFieldEntry.getKey(), dateTimeFieldEntry.getValue());
            }
        }

        return required;
    }

    private String getCallTest(final String className, final String functionName) {

        final String input = "package com.fivefaces.structuredpjapi.state.integration.calls;\n" +
                "\n" +
                "import com.fivefaces.structuredpjapi.state.integration.ParentStateTest;\n" +
                "import org.json.JSONArray;\n" +
                "import org.json.JSONObject;\n" +
                "import org.junit.jupiter.api.Test;\n" +
                "\n" +
                "import java.util.UUID;\n" +
                "\n" +
                "public class Call%sTest extends ParentStateTest {\n" +
                "\n" +
                "    private static final String FUNCTION_NAME = \"%s\";\n" +
                "\n" +
                "    @Override\n" +
                "    public String getValidateFunctionName() {\n" +
                "        return \"validate%s\";\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getRequiredRoles() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getStrings() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getIntegers() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getBooleans() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getArrays() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getDateTimes() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Test\n" +
                "    public void testCall%s_expecting_success() {\n" +
                "        JSONObject stepPayload = getJsonObject();\n" +
                "        expectSuccess(workflowService.instantiateSyncWorkflow(FUNCTION_NAME, stepPayload.toString()).getStatus());\n" +
                "\n" +
                "    }\n" +
                "}\n";

        return String.format(input, className, functionName, className, className);

    }

    private String getCreateTest(final String className, final String[] rolesArray,
                                 final Map stringFields,
                                 final Map integerFields,
                                 final Map booleanFields,
                                 final Map arrayFields,
                                 final Map dateTimeFields) {

        final String roles = getArrayProperties(rolesArray);
        final String strings = getArrayProperties(getRequiredStrings(stringFields, false).keySet().toArray(new String[0]));
        final String integers = getArrayProperties(getRequiredIntegers(integerFields).keySet().toArray(new String[0]));
        final String booleans = getArrayProperties(getRequiredBooleans(booleanFields).keySet().toArray(new String[0]));
        final String arrays = getArrayProperties(getRequiredArrays(arrayFields).keySet().toArray(new String[0]));
        final String dateTimes = getArrayProperties(getRequiredDateTimes(dateTimeFields).keySet().toArray(new String[0]));

        final String steps = getSteps(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);

        final String input = "package com.fivefaces.structuredpjapi.state.integration.%s;\n" +
                "\n" +
                "import com.fivefaces.structuredpjapi.state.integration.ParentStateTest;\n" +
                "import org.json.JSONArray;\n" +
                "import org.json.JSONObject;\n" +
                "import org.junit.jupiter.api.Test;\n" +
                "\n" +
                "import java.util.UUID;\n" +
                "\n" +
                "public class Create%sTest extends ParentStateTest {\n" +
                "\n" +
                "    private static final String FUNCTION_NAME = \"create%s\";\n" +
                "\n" +
                "    @Override\n" +
                "    public String getValidateFunctionName() {\n" +
                "        return \"validateCreate%s\";\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getRequiredRoles() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getStrings() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getIntegers() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getBooleans() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getArrays() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getDateTimes() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Test\n" +
                "    public void testCreate%s_expecting_success() {\n" +
                "        String id = String.valueOf(UUID.randomUUID());\n" +
                "        JSONObject stepPayload = getJsonObject();\n" +
                "        add(stepPayload, \"id\", id);\n" +
                "%s" +
                "\n" +
                "        expectSuccess(workflowService.instantiateSyncWorkflow(FUNCTION_NAME, stepPayload.toString()).getStatus());\n" +
                "\n" +
                "    }\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className, className, className, roles, strings, integers, booleans, arrays, dateTimes, className, steps);

    }

    private String getUpdateTest(final String className, final String tableName, final String[] rolesArray,
                                 final Map stringFields,
                                 final Map integerFields,
                                 final Map booleanFields,
                                 final Map arrayFields,
                                 final Map dateTimeFields) {

        final String roles = getArrayProperties(rolesArray);
        final String strings = getArrayProperties(getRequiredStrings(stringFields, true).keySet().toArray(new String[0]));
        final String integers = getArrayProperties(getRequiredIntegers(integerFields).keySet().toArray(new String[0]));
        final String booleans = getArrayProperties(getRequiredBooleans(booleanFields).keySet().toArray(new String[0]));
        final String arrays = getArrayProperties(getRequiredArrays(arrayFields).keySet().toArray(new String[0]));
        final String dateTimes = getArrayProperties(getRequiredDateTimes(dateTimeFields).keySet().toArray(new String[0]));

        final String steps = getSteps(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);

        final String input = "package com.fivefaces.structuredpjapi.state.integration.%s;\n" +
                "\n" +
                "import com.fivefaces.structuredpjapi.state.integration.ParentStateTest;\n" +
                "import com.fivefaces.common.util.JsonUtils;\n" +
                "import com.fivefaces.structure.entity.StructureEntity;\n" +
                "import com.fivefaces.testutils.%sUtils;\n" +
                "import org.json.JSONArray;\n" +
                "import org.json.JSONObject;\n" +
                "import org.junit.jupiter.api.Test;\n" +
                "\n" +
                "import java.util.UUID;\n" +
                "\n" +
                "public class Update%sTest extends ParentStateTest {\n" +
                "\n" +
                "    private static final String FUNCTION_NAME = \"update%s\";\n" +
                "    private static final String NOT_THE_REAL_USER = \"not_the_real_user\";\n" +
                "\n" +
                "    @Override\n" +
                "    public String getValidateFunctionName() {\n" +
                "        return \"validateUpdate%s\";\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getRequiredRoles() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getStrings() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getIntegers() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getBooleans() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getArrays() {\n" +
                "       return new String[]{%s};\n" +
                "    }\n" +
                "    @Override\n" +
                "    public String[] getDateTimes() {\n" +
                "       return new String[]{%s};\n" +
                "    }\n" +
                "    private StructureEntity createEntity() throws Exception {\n" +
                "        String json = new %sUtils().getJson();\n" +
                "        JSONObject query = new JSONObject(json);\n" +
                "        JSONObject insert = new JSONObject(\"{}\");\n" +
                "        insert.put(\"type\", \"%s\");\n" +
                "        insert.put(\"query\", query);\n" +
                "        StructureEntity structureEntity = structureService.insert(NOT_THE_REAL_USER, insert);\n" +
                "        cleanUpIds.put(structureEntity.getId(), \"%s\");\n" +
                "        return structureEntity;\n" +
                "    }" +
                "\n" +
                "    @Test\n" +
                "    public void testUpdate%s_expecting_success() throws Exception {\n" +
                "        final StructureEntity entity = createEntity();\n" +
                "        String app = structureService.queryById(\"%s\", UUID.fromString(entity.getId()), new JSONObject(\"{}\"));\n" +
                "        JSONObject appAsJson = (JSONObject) new JSONArray(new JsonUtils().unmarshall(app)).get(0);\n" +
                "        JSONObject stepPayload = getJsonObject();\n" +
                "        add(stepPayload, \"id\", entity.getId());\n" +
                "        add(stepPayload, \"version\", appAsJson.get(\"version\"));\n" +
                "%s" +
                "\n" +
                "        expectSuccess(workflowService.instantiateSyncWorkflow(FUNCTION_NAME, stepPayload.toString()).getStatus());\n" +
                "        }\n" +
                "\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className, className, className, className, roles, strings, integers, booleans, arrays, dateTimes,
                className, tableName, tableName.toLowerCase(Locale.ROOT), className,
                tableName, steps);

    }

    private String getDeleteTest(final String className, final String tableName, final String[] rolesArray) {

        final String roles = getArrayProperties(rolesArray);

        final String input = "package com.fivefaces.structuredpjapi.state.integration.%s;\n" +
                "\n" +
                "import com.fivefaces.structuredpjapi.state.integration.ParentStateTest;\n" +
                "import com.fivefaces.structure.entity.StructureEntity;\n" +
                "import com.fivefaces.testutils.%sUtils;\n" +
                "import org.json.JSONObject;\n" +
                "import org.junit.jupiter.api.Test;\n" +
                "\n" +
                "import static org.junit.jupiter.api.Assertions.assertEquals;\n" +
                "import static org.junit.jupiter.api.Assertions.fail;\n" +
                "\n" +
                "public class Delete%sTest extends ParentStateTest {\n" +
                "\n" +
                "    private static final String FUNCTION_NAME = \"delete%s\";\n" +
                "    private static final String NOT_THE_REAL_USER = \"not_the_real_user\";\n" +
                "\n" +
                "    @Override\n" +
                "    public String getValidateFunctionName() {\n" +
                "        return \"validateDelete%s\";\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getRequiredRoles() {\n" +
                "        return new String[]{%s};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getStrings() {\n" +
                "        return new String[]{\"id\"};\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getIntegers() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getBooleans() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getArrays() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    @Override\n" +
                "    public String[] getDateTimes() {\n" +
                "        return new String[0];\n" +
                "    }\n" +
                "\n" +
                "    private StructureEntity createEntity() throws Exception {\n" +
                "        String json = new %sUtils().getJson();\n" +
                "        JSONObject query = new JSONObject(json);\n" +
                "        JSONObject insert = new JSONObject(\"{}\");\n" +
                "        insert.put(\"type\", \"%s\");\n" +
                "        insert.put(\"query\", query);\n" +
                "        StructureEntity structureEntity = structureService.insert(NOT_THE_REAL_USER, insert);\n" +
                "        cleanUpIds.put(structureEntity.getId(), \"%s\");\n" +
                "        return structureEntity;\n" +
                "    }\n" +
                "    @Test\n" +
                "    public void testDelete%s_expecting_success() throws Exception {\n" +
                "\n" +
                "        final StructureEntity entity = createEntity();\n" +
                "\n" +
                "        JSONObject query = new JSONObject(\"{\\n\" +\n" +
                "                \"  \\\"type\\\": \\\"%s\\\",\\n\" +\n" +
                "                \"  \\\"count\\\" : true,\\n\" +\n" +
                "                \"  \\\"criteria\\\": [\\n\" +\n" +
                "                \"    {\\n\" +\n" +
                "                \"      \\\"member\\\": \\\"$.id\\\",\\n\" +\n" +
                "                \"      \\\"type\\\": \\\"eq\\\",\\n\" +\n" +
                "                \"      \\\"string\\\": true,\\n\" +\n" +
                "                \"      \\\"value\\\": \\\"\" + entity.getId() + \"\\\"\\n\" +\n" +
                "                \"    }\\n\" +\n" +
                "                \"  ]\\n\" +\n" +
                "                \"}\");\n" +
                "\n" +
                "        String existingEntity = structureService.query(query, \"\");\n" +
                "        assertEquals(\"1\", existingEntity);\n" +
                "\n" +
                "\n" +
                "        JSONObject json = getJsonObject(\"ADMIN\");\n" +
                "        add(json, \"id\", entity.getId());\n" +
                "        String result = workflowService.instantiateSyncWorkflow(FUNCTION_NAME, json.toString()).getStatus();\n" +
                "        if (result.contains(\"FAILED\")) {\n" +
                "            fail(result);\n" +
                "        }\n" +
                "\n" +
                "        final String deletedEntity = structureService.query(query, \"\");\n" +
                "        assertEquals(\"0\", deletedEntity);\n" +
                "\n" +
                "    }\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className, className, className, className, roles,
                className, tableName, tableName.toLowerCase(Locale.ROOT),
                className, tableName);

    }

    private String getCreateAWSOnPremTest(final String className) {

        final String input = "package com.fivefaces.structuredpjapi.state.integration.awsonprem.%s;\n" +
                "\n" +
                "\n" +
                "import com.fivefaces.StructureApplication;\n" +
                "import com.fivefaces.structuredpjapi.state.integration.%s.Create%sTest;\n" +
                "import org.springframework.boot.test.context.SpringBootTest;\n" +
                "import org.springframework.test.context.ActiveProfiles;\n" +
                "\n" +
                "@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = StructureApplication.class)\n" +
                "@ActiveProfiles({\"test\", \"WORKFLOW_AWS_ON_PREM\", \"SETTING_DATABASE\", \"FILE_STORAGE_FILE\", \"WAREHOUSE_AWS_MYSQL\", \"SMS_AWS_SNS\", \"MEETING_AZURE\", \"INTEGRATION_NONE\", \"INTEGRATION_NONE\"})\n" +
                "public class AWSOnPremiseCreate%sTest extends Create%sTest {\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className.toLowerCase(Locale.ROOT), className, className, className);

    }

    private String getUpdateAWSOnPremTest(final String className) {

        final String input = "package com.fivefaces.structuredpjapi.state.integration.awsonprem.%s;\n" +
                "\n" +
                "\n" +
                "import com.fivefaces.StructureApplication;\n" +
                "import com.fivefaces.structuredpjapi.state.integration.%s.Update%sTest;\n" +
                "import org.springframework.boot.test.context.SpringBootTest;\n" +
                "import org.springframework.test.context.ActiveProfiles;\n" +
                "\n" +
                "@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = StructureApplication.class)\n" +
                "@ActiveProfiles({\"test\", \"WORKFLOW_AWS_ON_PREM\", \"SETTING_DATABASE\", \"FILE_STORAGE_FILE\", \"WAREHOUSE_AWS_MYSQL\", \"SMS_AWS_SNS\", \"MEETING_AZURE\", \"INTEGRATION_NONE\", \"INTEGRATION_NONE\"})\n" +
                "public class AWSOnPremiseUpdate%sTest extends Update%sTest {\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className.toLowerCase(Locale.ROOT), className, className, className);

    }

    private String getCallAWSOnPremTest(final String className) {

        final String input = "package com.fivefaces.structuredpjapi.state.integration.awsonprem.calls;\n" +
                "\n" +
                "\n" +
                "import com.fivefaces.StructureApplication;\n" +
                "import com.fivefaces.structuredpjapi.state.integration.calls.Call%sTest;\n" +
                "import org.springframework.boot.test.context.SpringBootTest;\n" +
                "import org.springframework.test.context.ActiveProfiles;\n" +
                "\n" +
                "@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = StructureApplication.class)\n" +
                "@ActiveProfiles({\"test\", \"WORKFLOW_AWS_ON_PREM\", \"SETTING_DATABASE\", \"FILE_STORAGE_FILE\", \"WAREHOUSE_AWS_MYSQL\", \"SMS_AWS_SNS\", \"MEETING_AZURE\", \"INTEGRATION_NONE\", \"INTEGRATION_NONE\"})\n" +
                "public class AWSOnPremiseCall%sTest extends Call%sTest {\n" +
                "}\n";

        return String.format(input, className, className, className);

    }

    private String getDeleteAWSOnPremTest(final String className) {

        final String input = "package com.fivefaces.structuredpjapi.state.integration.awsonprem.%s;\n" +
                "\n" +
                "\n" +
                "import com.fivefaces.StructureApplication;\n" +
                "import com.fivefaces.structuredpjapi.state.integration.%s.Delete%sTest;\n" +
                "import org.springframework.boot.test.context.SpringBootTest;\n" +
                "import org.springframework.test.context.ActiveProfiles;\n" +
                "\n" +
                "@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = StructureApplication.class)\n" +
                "@ActiveProfiles({\"test\", \"WORKFLOW_AWS_ON_PREM\", \"SETTING_DATABASE\", \"FILE_STORAGE_FILE\", \"WAREHOUSE_AWS_MYSQL\", \"SMS_AWS_SNS\", \"MEETING_AZURE\", \"INTEGRATION_NONE\", \"INTEGRATION_NONE\"})\n" +
                "public class AWSOnPremiseDelete%sTest extends Delete%sTest {\n" +
                "}\n";

        return String.format(input, className.toLowerCase(Locale.ROOT), className.toLowerCase(Locale.ROOT), className, className, className);

    }


    private String getCreateMethod(final String className,
                                   final String tableName,
                                   final boolean warehouse,
                                   final String insertText,
                                   final Map stringFields,
                                   final Map integerFields,
                                   final Map booleanFields,
                                   final Map arrayFields,
                                   final Map dateTimeFields) {
        final String properties = getProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);

        final String input = "resource \"aws_sfn_state_machine\" \"create%s\" {\n" +
                "  name       = \"${var.environment}_create%s\"\n" +
                "  role_arn   = aws_iam_role.step_function_role.arn\n" +
                "  type       = \"STANDARD\"\n" +
                "  definition = < stringFields,
                                          Map integerFields,
                                          Map booleanFields,
                                          Map arrayFields,
                                          Map dateTimeFields) {
        if (!warehouse) return "";

        final StringBuilder result = new StringBuilder("\"warehouse\": true, \"primaryUpdates\":[");


        if (stringFields != null) {
            stringFields.forEach((key, value) -> {
                if (value != null && value.warehousePrimary()) {
                    result.append("\"").append(key).append("\",");
                }
            });
            integerFields.forEach((key, value) -> {
                if (value != null && value.primary()) {
                    result.append("\"").append(key).append("\",");
                }
            });
            booleanFields.forEach((key, value) -> {
                if (value != null && value.primary()) {
                    result.append("\"").append(key).append("\",");
                }
            });
            arrayFields.forEach((key, value) -> {
                if (value != null && value.primary()) {
                    result.append("\"").append(key).append("\",");
                }
            });
            dateTimeFields.forEach((key, value) -> {
                if (value != null && value.primary()) {
                    result.append("\"").append(key).append("\",");
                }
            });

            if (result.toString().endsWith("[")) {
                return result + "],";
            }
            return result.substring(0, result.length() - 1) + "],";
        } else {
            return result + "],";
        }

    }

    private String getInsertProperties(final boolean insert, Map stringFields,
                                       Map integerFields,
                                       Map booleanFields,
                                       Map arrayFields,
                                       Map dateTimeFields) {

        final StringBuilder result = new StringBuilder();

        final StringBuilder associations = new StringBuilder("\t\t\t\"associations\": [");

        final Boolean[] hasAssociations = new Boolean[]{false};
        stringFields.forEach((key, value) -> {
            if (value != null && !value.association()) {
                if (insert) {
                    if (value.createValue().isEmpty()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    } else {
                        result.append("\t\t\t\"").append(key).append("\": \"").append(value.createValue()).append("\",\n");
                    }
                } else {
                    if (value.updateable()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    }
                }
            } else if (value != null) {
                hasAssociations[0] = true;
                if (insert) {
                    associations.append("\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"").append(value.description()).append("\",\n\t\t\t\t\t\"id.$\": \"$.query.").append(key).append("\"\n\t\t\t\t},");
                }
//                } else {
//                    if (value.updateable()) {
//                        associations.append("\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"").append(value.description()).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) + "]";

        integerFields.forEach((key, value) -> {
            if (value != null) {
                if (insert) {
                    result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                } else {
                    if (value.updateable()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    }
                }
            }
        });

        booleanFields.forEach((key, value) -> {
            if (value != null) {
                if (insert) {
                    result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                } else {
                    if (value.updateable()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    }
                }
            }
        });

        arrayFields.forEach((key, value) -> {
            if (value != null) {
                if (insert) {
                    result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                } else {
                    if (value.updateable()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    }
                }
            }
        });

        dateTimeFields.forEach((key, value) -> {
            if (value != null) {
                if (insert) {
                    result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                } else {
                    if (value.updateable()) {
                        result.append("\t\t\t\"").append(key).append(".$\": \"$.query.").append(key).append("\",\n");
                    }
                }
            }
        });


        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 className, final String tableName, final String[] rolesArray,
                                           final Map stringFields,
                                           final Map integerFields,
                                           final Map booleanFields,
                                           final Map arrayFields,
                                           final Map dateTimeFields) {

        final String properties = getProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);
        final String required = getRequiredProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields, false);
        final String unique = getUniqueProperties(stringFields, integerFields);
        final String roles = getArrayProperties(rolesArray);
        final String input = "resource \"aws_sfn_state_machine\" \"validateCreate%s\" {\n" +
                "  name       = \"${var.environment}_validateCreate%s\"\n" +
                "  role_arn   = aws_iam_role.step_function_role.arn\n" +
                "  type       = \"EXPRESS\"\n" +
                "  definition = < stringFields,
                                           final Map integerFields,
                                           final Map booleanFields,
                                           final Map arrayFields,
                                           final Map dateTimeFields) {

        final String properties = getProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);
        final String required = getRequiredProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields, false);
        final String unique = getUniqueProperties(stringFields, integerFields);
        final String roles = getArrayProperties(rolesArray);
        final String input = "resource \"aws_sfn_state_machine\" \"validate%s\" {\n" +
                "  name       = \"${var.environment}_validate%s\"\n" +
                "  role_arn   = aws_iam_role.step_function_role.arn\n" +
                "  type       = \"EXPRESS\"\n" +
                "  definition = < stringFields,
                                           final Map integerFields,
                                           final Map booleanFields,
                                           final Map arrayFields,
                                           final Map dateTimeFields) {

        final String properties = getProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);
        final String required = getRequiredProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields, true);
        final String unique = getUniqueProperties(stringFields, integerFields);
        final String roles = getArrayProperties(rolesArray);
        final String input = "resource \"aws_sfn_state_machine\" \"validateUpdate%s\" {\n" +
                "  name       = \"${var.environment}_validateUpdate%s\"\n" +
                "  role_arn   = aws_iam_role.step_function_role.arn\n" +
                "  type       = \"EXPRESS\"\n" +
                "  definition = < stringFields,
                                   final Map integerFields,
                                   final Map booleanFields,
                                   final Map arrayFields,
                                   final Map dateTimeFields) {

        final String properties = getProperties(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);

        final String input = "resource \"aws_sfn_state_machine\" \"update%s\" {\n" +
                "  name       = \"${var.environment}_update%s\"\n" +
                "  role_arn   = aws_iam_role.step_function_role.arn\n" +
                "  type       = \"STANDARD\"\n" +
                "  definition = < stringFields,
                                 Map integerFields,
                                 Map booleanFields,
                                 Map arrayFields,
                                 Map dateTimeFields) {

        final StringBuilder result = new StringBuilder();

        stringFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(value.description()).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.type()).append("\"");
                if (value.minLength() >= 0) {
                    result.append(",\"minLength\":").append(value.minLength());
                }
                if (value.maxLength() >= 0) {
                    result.append(",\"maxLength\":").append(value.maxLength());
                }
                result.append("\n\t\t\t\t},\n");
            }
        });

        integerFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(value.description()).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.type()).append("\"");
                result.append("\n\t\t\t\t},\n");
            }
        });

        booleanFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(value.description()).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.type()).append("\"");
                result.append("\n\t\t\t\t},\n");
            }
        });

        arrayFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(value.description()).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"").append(value.type()).append("\"");
                result.append("\n\t\t\t\t},\n");
            }
        });

        dateTimeFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\"").append(key).append("\": {\n");
                result.append("\t\t\t\t\t\"description\": \"").append(value.description()).append("\",\n");
                result.append("\t\t\t\t\t\"type\": \"string\",\"format\": \"date-time\"");
                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 getPropertiesForJava(Map stringFields,
                                        Map integerFields,
                                        Map booleanFields,
                                        Map arrayFields,
                                        Map dateTimeFields) {

        final StringBuilder result = new StringBuilder("{");

        stringFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\\\"").append(key).append("\\\": {");
                result.append("\t\t\t\t\t\\\"description\\\": \\\"").append(value.description()).append("\\\",");
                result.append("\t\t\t\t\t\\\"type\\\": \\\"").append(value.type()).append("\\\"");
                if (value.minLength() >= 0) {
                    result.append(",\\\"minLength\\\":").append(value.minLength());
                }
                if (value.maxLength() >= 0) {
                    result.append(",\\\"maxLength\\\":").append(value.maxLength());
                }
                result.append("\t\t\t\t},");
            }
        });

        integerFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\\\"").append(key).append("\\\": {");
                result.append("\t\t\t\t\t\\\"description\\\": \\\"").append(value.description()).append("\\\",");
                result.append("\t\t\t\t\t\\\"type\\\": \\\"").append(value.type()).append("\\\"");
                result.append("\t\t\t\t},");
            }
        });

        booleanFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\\\"").append(key).append("\\\": {");
                result.append("\t\t\t\t\t\\\"description\\\": \\\"").append(value.description()).append("\\\",");
                result.append("\t\t\t\t\t\\\"type\\\": \\\"").append(value.type()).append("\\\"");
                result.append("\t\t\t\t},");
            }
        });

        arrayFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\\\"").append(key).append("\\\": {");
                result.append("\t\t\t\t\t\\\"description\\\": \\\"").append(value.description()).append("\\\",");
                result.append("\t\t\t\t\t\\\"type\\\": \\\"").append(value.type()).append("\\\"");
                result.append("\t\t\t\t},");
            }
        });

        dateTimeFields.forEach((key, value) -> {
            if (value != null) {
                result.append("\t\t\t\t\\\"").append(key).append("\\\": {");
                result.append("\t\t\t\t\t\\\"description\\\": \\\"").append(value.description()).append("\\\",");
                result.append("\t\t\t\t\t\\\"type\\\": \\\"string\\\",\\\"format\\\": \\\"date-time\\\"");
                result.append("\t\t\t\t},");
            }
        });

        return result.substring(0, result.lastIndexOf(",") - 1) + "}}\"";
    }

    private String getRequiredProperties(Map stringFields,
                                         Map integerFields,
                                         Map booleanFields,
                                         Map arrayFields,
                                         Map dateTimeFields,
                                         final boolean update) {

        final StringBuilder result = new StringBuilder();

        stringFields.forEach((key, value) -> {
            if (value != null && value.required()) {
                if (update && value.association()) {
                    // not adding associations to update as they will be done with embedded
                } else {
                    result.append("\"").append(key).append("\",");
                }
            }
        });
        integerFields.forEach((key, value) -> {
            if (value != null && value.required()) {
                result.append("\"").append(key).append("\",");
            }
        });
        booleanFields.forEach((key, value) -> {
            if (value != null && value.required()) {
                result.append("\"").append(key).append("\",");
            }
        });
        arrayFields.forEach((key, value) -> {
            if (value != null && value.required()) {
                result.append("\"").append(key).append("\",");
            }
        });
        dateTimeFields.forEach((key, value) -> {
            if (value != null && value.required()) {
                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 stringFields,
                                       Map integerFields) {

        final StringBuilder result = new StringBuilder();

        stringFields.forEach((key, value) -> {
            if (value != null && value.unique()) {
                result.append("\"").append(key).append("\",");
            }
        });
        integerFields.forEach((key, value) -> {
            if (value != null && value.unique()) {
                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);
    }


    public String createWarehouseTable(final Map stringFields,
                                       final Map integerFields,
                                       final Map booleanFields,
                                       final Map arrayFields,
                                       final Map dateTimeFields,
                                       final String schemaName, final String tableName) {

        final String properties = getPropertiesForJava(stringFields, integerFields, booleanFields, arrayFields, dateTimeFields);

        String noTabs = properties.replaceAll("\\t", "").replaceAll("\\n","").replaceAll("\\\\","");
        final JSONObject jsonObject = new JSONObject(noTabs);

        final Set keys = jsonObject.keySet();
        final StringBuilder fields = new StringBuilder();
        keys.forEach(fieldName -> {
            JSONObject definition = jsonObject.getJSONObject(fieldName);
            if (fieldName.equals("id")) {
                fields.append("`").append(fieldName).append("` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,\n");
            } else {
                final String type = definition.getString("type");
                switch (type) {
                    case "string":
                        if (definition.has("format")) {
                            final String format = definition.getString("format");
                            if (format.equals("date-time")) {
                                fields.append("`").append(fieldName).append("` varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci  DEFAULT NULL,\n");
                            }
                        } else {
                            int length = 300;
                            if (definition.has("maxLength")) {
                                length = definition.getInt("maxLength");
                            }
                            fields.append("`").append(fieldName).append("` varchar(").append(length).append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n");
                        }
                        break;
                    case "array":
                        fields.append("`").append(fieldName).append("` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,\n");
                        break;
                    case "boolean":
                        fields.append("`").append(fieldName).append("` boolean DEFAULT NULL,\n");
                        break;
                    case "integer":
                        fields.append("`").append(fieldName).append("` int DEFAULT NULL,\n");
                        break;
                }
            }
        });

        final String createTable = String.format("CREATE TABLE `%s`.`%s` (%s \n`last_modified_at_utc` datetime NOT NULL,\n`last_modified_by` varchar(40), \n`effective_date` datetime NOT NULL, \n`expired_date` datetime NOT NULL, `original_json` JSON NOT NULL, `id` varchar(40) NOT NULL, `version` int NOT NULL,  PRIMARY KEY (`id`,`effective_date`)) \nENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n\n", schemaName, tableName, fields);

        return createTable;

    }

    private String getIndexProperties(final String tableName, final String warehouseSchema, Map stringFields,
                                          Map integerFields) {


        final StringBuilder indexs = new StringBuilder();
        final StringBuilder result = new StringBuilder();
        if (stringFields != null) {
            stringFields.forEach((key, value) -> {
                if (value.index()) {
                    if (value.maxLength() > 0) {
                        result.append("ALTER TABLE `").append(tableName).append("` ADD COLUMN `").append(key).append("_stored` VARCHAR(").append(value.maxLength()).append(") GENERATED ALWAYS AS (`json_data` ->> '$.").append(key).append("') STORED NOT NULL ;\n");
                    } else {
                        result.append("ALTER TABLE `").append(tableName).append("` ADD COLUMN `").append(key).append("_stored` VARCHAR(300) GENERATED ALWAYS AS (`json_data` ->> '$.").append(key).append("') STORED NOT NULL ;\n");
                    }
                    result.append("CREATE INDEX `").append(key).append("_idx` ON `").append(tableName).append("`(`").append(key).append("_stored`);\n");
                    indexs.append(key).append(",");
                }
            });
            integerFields.forEach((key, value) -> {
                if (value.index()) {
                    result.append("ALTER TABLE `").append(tableName).append("` ADD COLUMN `").append(key).append("_stored` INT GENERATED ALWAYS AS (`json_data` ->> '$.").append(key).append("') STORED NOT NULL ;\n");
                    result.append("CREATE INDEX `").append(key).append("_idx` ON `").append(tableName).append("`(`").append(key).append("_stored`);\n");
                }
            });
        }

        if (!indexs.toString().isEmpty()) {
            if (stringFields != null) {
                stringFields.forEach((key, value) -> {
                    if (value.index()) {
                        result.append("ALTER TABLE `").append(warehouseSchema).append("`.`").append(tableName).append("` ADD UNIQUE INDEX `").append(key).append("_UNIQUE` (`").append(key).append("` ASC) VISIBLE;\n");
                    }
                });
                integerFields.forEach((key, value) -> {
                    if (value.index()) {
                        result.append("ALTER TABLE `").append(warehouseSchema).append("`.`").append(tableName).append("` ADD UNIQUE INDEX `").append(key).append("_UNIQUE` (`").append(key).append("` ASC) VISIBLE;\n");                    }
                });
            }

            result.append("\n\n *** These entries need to live in the properties file for the project ***\n\n");
            result.append("index.").append(tableName).append("=").append(indexs.substring(0, indexs.length() - 1));
        }

        return result.toString();

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy