From 12a92c63304f9b57e265d01e137dfb60d0e84f61 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 5 Apr 2023 10:03:10 -0500 Subject: [PATCH] Recursively add all association component schemas; add recordCount to bulk api action logs --- .../actions/GenerateOpenApiSpecAction.java | 100 ++++++++++++++---- .../qqq/api/javalin/QJavalinApiHandler.java | 6 +- .../GenerateOpenApiSpecActionTest.java | 45 +++++++- 3 files changed, 128 insertions(+), 23 deletions(-) diff --git a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/GenerateOpenApiSpecAction.java b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/GenerateOpenApiSpecAction.java index aab67fe5..537548d2 100644 --- a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/GenerateOpenApiSpecAction.java +++ b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/GenerateOpenApiSpecAction.java @@ -27,9 +27,11 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Comparator; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import com.kingsrook.qqq.api.model.APIVersion; import com.kingsrook.qqq.api.model.APIVersionRange; import com.kingsrook.qqq.api.model.actions.GenerateOpenApiSpecInput; @@ -181,6 +183,8 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction neededTableSchemas = new HashSet<>(); + /******************************************************************************* @@ -386,23 +390,9 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction tableFields = new LinkedHashMap<>(); - Schema tableSchema = new Schema() - .withType("object") - .withProperties(tableFields); + Schema tableSchema = buildTableSchema(apiInstanceMetaData, table, tableApiFields); componentSchemas.put(tableApiName, tableSchema); - for(QFieldMetaData field : tableApiFields) - { - Schema fieldSchema = getFieldSchema(table, field); - tableFields.put(ApiFieldMetaData.getEffectiveApiFieldName(apiInstanceMetaData.getName(), field), fieldSchema); - } - - ////////////////////////////////// - // recursively add associations // - ////////////////////////////////// - addAssociations(apiName, table, tableSchema); - ////////////////////////////////////////////////////////////////////////////// // table as a search result (the base search result, plus the table itself) // ////////////////////////////////////////////////////////////////////////////// @@ -665,6 +655,8 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction componentSchemas) throws QException + { + String apiName = apiInstanceMetaData.getName(); + + boolean addedAny; + do + { + ////////////////////////////////////////////////////////////////////////// + // mmm, kinda odd loops, to avoid concurrent modification, and so-forth // + ////////////////////////////////////////////////////////////////////////// + addedAny = false; + for(String neededTableSchema : neededTableSchemas) + { + if(!componentSchemas.containsKey(neededTableSchema)) + { + LOG.debug("Adding needed schema: " + neededTableSchema); + QTableMetaData table = QContext.getQInstance().getTable(neededTableSchema); + + ApiTableMetaDataContainer apiTableMetaDataContainer = ApiTableMetaDataContainer.of(table); + ApiTableMetaData apiTableMetaData = apiTableMetaDataContainer.getApiTableMetaData(apiName); + + String tableApiName = StringUtils.hasContent(apiTableMetaData.getApiTableName()) ? apiTableMetaData.getApiTableName() : table.getName(); + + List tableApiFields = new GetTableApiFieldsAction().execute(new GetTableApiFieldsInput() + .withTableName(table.getName()) + .withVersion(version) + .withApiName(apiName)).getFields(); + + componentSchemas.put(tableApiName, buildTableSchema(apiInstanceMetaData, table, tableApiFields)); + addedAny = true; + break; + } + } + } + while(addedAny); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private Schema buildTableSchema(ApiInstanceMetaData apiInstanceMetaData, QTableMetaData table, List tableApiFields) + { + LinkedHashMap tableFields = new LinkedHashMap<>(); + Schema tableSchema = new Schema() + .withType("object") + .withProperties(tableFields); + + for(QFieldMetaData field : tableApiFields) + { + Schema fieldSchema = getFieldSchema(table, field); + tableFields.put(ApiFieldMetaData.getEffectiveApiFieldName(apiInstanceMetaData.getName(), field), fieldSchema); + } + + ////////////////////////////////// + // recursively add associations // + ////////////////////////////////// + addAssociations(apiInstanceMetaData.getName(), table, tableSchema); + + return (tableSchema); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -800,7 +862,7 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction ApiTableMetaDataContainer.of(associatedTable).getApiTableMetaData(apiName), new ApiTableMetaData()); String associatedTableApiName = StringUtils.hasContent(associatedApiTableMetaData.getApiTableName()) ? associatedApiTableMetaData.getApiTableName() : associatedTableName; + neededTableSchemas.add(associatedTable.getName()); + tableSchema.getProperties().put(association.getName(), new Schema() .withType("array") .withItems(new Schema().withRef("#/components/schemas/" + associatedTableApiName))); @@ -823,8 +887,8 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction