mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Recursively add all association component schemas; add recordCount to bulk api action logs
This commit is contained in:
@ -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<GenerateO
|
||||
* Each input primary key will also be included in the corresponding response object.
|
||||
""";
|
||||
|
||||
private Set<String> neededTableSchemas = new HashSet<>();
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -386,23 +390,9 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
//////////////////////////////////////
|
||||
// build the schemas for this table //
|
||||
//////////////////////////////////////
|
||||
LinkedHashMap<String, Schema> 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<GenerateO
|
||||
componentResponses.put("error" + HttpStatus.TOO_MANY_REQUESTS.getCode(), buildStandardErrorResponse("Too Many Requests. Your application has issued too many API requests in too short of a time frame."));
|
||||
}
|
||||
|
||||
ensureAllNeededTableSchemasExist(apiInstanceMetaData, version, componentSchemas);
|
||||
|
||||
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecOutput();
|
||||
output.setOpenAPI(openAPI);
|
||||
output.setYaml(YamlUtils.toYaml(openAPI));
|
||||
@ -674,6 +666,76 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** written for the use-case of, generating a single table's api, but it has
|
||||
** associations that it references, so we need their schemas too - so, make
|
||||
** sure they are all added to the componentSchemas map.
|
||||
*******************************************************************************/
|
||||
private void ensureAllNeededTableSchemasExist(ApiInstanceMetaData apiInstanceMetaData, String version, LinkedHashMap<String, Schema> 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<QFieldMetaData> 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<QFieldMetaData> tableApiFields)
|
||||
{
|
||||
LinkedHashMap<String, Schema> 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<GenerateO
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void addAssociations(String apiName, QTableMetaData table, Schema tableSchema)
|
||||
private void addAssociations(String apiName, QTableMetaData table, Schema tableSchema)
|
||||
{
|
||||
for(Association association : CollectionUtils.nonNullList(table.getAssociations()))
|
||||
{
|
||||
@ -809,6 +871,8 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
ApiTableMetaData associatedApiTableMetaData = ObjectUtils.tryElse(() -> 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<GenerateO
|
||||
private Schema getFieldSchema(QTableMetaData table, QFieldMetaData field)
|
||||
{
|
||||
Schema fieldSchema = new Schema()
|
||||
.withType(getFieldType(table.getField(field.getName())))
|
||||
.withFormat(getFieldFormat(table.getField(field.getName())))
|
||||
.withType(getFieldType(field))
|
||||
.withFormat(getFieldFormat(field))
|
||||
.withDescription(field.getLabel() + " for the " + table.getLabel() + ".");
|
||||
|
||||
if(!field.getIsEditable())
|
||||
|
@ -1504,7 +1504,7 @@ public class QJavalinApiHandler
|
||||
}
|
||||
}
|
||||
|
||||
QJavalinAccessLogger.logEndSuccess();
|
||||
QJavalinAccessLogger.logEndSuccess(logPair("recordCount", insertInput.getRecords().size()));
|
||||
context.status(HttpStatus.Code.MULTI_STATUS.getCode());
|
||||
String resultString = JsonUtils.toJson(response);
|
||||
context.result(resultString);
|
||||
@ -1636,7 +1636,7 @@ public class QJavalinApiHandler
|
||||
i++;
|
||||
}
|
||||
|
||||
QJavalinAccessLogger.logEndSuccess();
|
||||
QJavalinAccessLogger.logEndSuccess(logPair("recordCount", updateInput.getRecords().size()));
|
||||
context.status(HttpStatus.Code.MULTI_STATUS.getCode());
|
||||
String resultString = JsonUtils.toJson(response);
|
||||
context.result(resultString);
|
||||
@ -1777,7 +1777,7 @@ public class QJavalinApiHandler
|
||||
}
|
||||
}
|
||||
|
||||
QJavalinAccessLogger.logEndSuccess();
|
||||
QJavalinAccessLogger.logEndSuccess(logPair("recordCount", deleteInput.getPrimaryKeys().size()));
|
||||
context.status(HttpStatus.Code.MULTI_STATUS.getCode());
|
||||
String resultString = JsonUtils.toJson(response);
|
||||
context.result(resultString);
|
||||
|
@ -25,8 +25,11 @@ package com.kingsrook.qqq.api.actions;
|
||||
import java.util.Set;
|
||||
import com.kingsrook.qqq.api.BaseTest;
|
||||
import com.kingsrook.qqq.api.TestUtils;
|
||||
import com.kingsrook.qqq.api.model.APIVersion;
|
||||
import com.kingsrook.qqq.api.model.actions.GenerateOpenApiSpecInput;
|
||||
import com.kingsrook.qqq.api.model.actions.GenerateOpenApiSpecOutput;
|
||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
@ -53,8 +56,46 @@ class GenerateOpenApiSpecActionTest extends BaseTest
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecAction().execute(new GenerateOpenApiSpecInput().withVersion(TestUtils.CURRENT_API_VERSION).withApiName(TestUtils.API_NAME));
|
||||
System.out.println(output.getYaml());
|
||||
for(ApiInstanceMetaData apiInstanceMetaData : ApiInstanceMetaDataContainer.of(QContext.getQInstance()).getApis().values())
|
||||
{
|
||||
for(APIVersion supportedVersion : apiInstanceMetaData.getSupportedVersions())
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// just making sure we don't throw on any apis in the test instance //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecAction().execute(new GenerateOpenApiSpecInput()
|
||||
.withVersion(supportedVersion.toString())
|
||||
.withApiName(apiInstanceMetaData.getName()));
|
||||
// System.out.println(output.getYaml());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testSingleTable() throws QException
|
||||
{
|
||||
for(ApiInstanceMetaData apiInstanceMetaData : ApiInstanceMetaDataContainer.of(QContext.getQInstance()).getApis().values())
|
||||
{
|
||||
for(APIVersion supportedVersion : apiInstanceMetaData.getSupportedVersions())
|
||||
{
|
||||
for(QTableMetaData table : QContext.getQInstance().getTables().values())
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// just making sure we don't throw on any apis in the test instance //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecAction().execute(new GenerateOpenApiSpecInput()
|
||||
.withTableName(table.getName())
|
||||
.withVersion(supportedVersion.toString())
|
||||
.withApiName(apiInstanceMetaData.getName()));
|
||||
// System.out.println(output.getYaml());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user