mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Initial implementation of api processes
This commit is contained in:
@ -57,6 +57,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponen
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QSupplementalProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
|
||||||
@ -367,6 +368,11 @@ public class QInstanceEnricher
|
|||||||
process.getStepList().forEach(this::enrichStep);
|
process.getStepList().forEach(this::enrichStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(QSupplementalProcessMetaData supplementalProcessMetaData : CollectionUtils.nonNullMap(process.getSupplementalMetaData()).values())
|
||||||
|
{
|
||||||
|
supplementalProcessMetaData.enrich(process);
|
||||||
|
}
|
||||||
|
|
||||||
enrichPermissionRules(process);
|
enrichPermissionRules(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@ package com.kingsrook.qqq.backend.core.model.actions.processes;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobCallback;
|
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobCallback;
|
||||||
@ -31,6 +35,7 @@ import com.kingsrook.qqq.backend.core.context.QContext;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -183,6 +188,17 @@ public class RunProcessInput extends AbstractActionInput
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public RunProcessInput withValue(String fieldName, Serializable value)
|
||||||
|
{
|
||||||
|
this.processState.getValues().put(fieldName, value);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for values
|
** Setter for values
|
||||||
**
|
**
|
||||||
@ -258,7 +274,7 @@ public class RunProcessInput extends AbstractActionInput
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public String getValueString(String fieldName)
|
public String getValueString(String fieldName)
|
||||||
{
|
{
|
||||||
return ((String) getValue(fieldName));
|
return (ValueUtils.getValueAsString(getValue(fieldName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -269,7 +285,67 @@ public class RunProcessInput extends AbstractActionInput
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Integer getValueInteger(String fieldName)
|
public Integer getValueInteger(String fieldName)
|
||||||
{
|
{
|
||||||
return ((Integer) getValue(fieldName));
|
return (ValueUtils.getValueAsInteger(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public BigDecimal getValueBigDecimal(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsBigDecimal(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getValueBoolean(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsBoolean(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public LocalTime getValueLocalTime(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsLocalTime(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public LocalDate getValueLocalDate(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsLocalDate(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public byte[] getValueByteArray(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsByteArray(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Instant getValueInstant(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsInstant(getValue(fieldName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,11 +23,16 @@ package com.kingsrook.qqq.backend.core.model.actions.processes;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -122,6 +127,99 @@ public class RunProcessOutput extends AbstractActionOutput implements Serializab
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for a single field's value
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Serializable getValue(String fieldName)
|
||||||
|
{
|
||||||
|
return (this.processState.getValues().get(fieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for a single field's value
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getValueString(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsString(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for a single field's value
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer getValueInteger(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsInteger(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public BigDecimal getValueBigDecimal(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsBigDecimal(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getValueBoolean(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsBoolean(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public LocalTime getValueLocalTime(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsLocalTime(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public LocalDate getValueLocalDate(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsLocalDate(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public byte[] getValueByteArray(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsByteArray(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Instant getValueInstant(String fieldName)
|
||||||
|
{
|
||||||
|
return (ValueUtils.getValueAsInstant(getValue(fieldName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for values
|
** Setter for values
|
||||||
**
|
**
|
||||||
@ -133,6 +231,17 @@ public class RunProcessOutput extends AbstractActionOutput implements Serializab
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public RunProcessOutput withValue(String fieldName, Serializable value)
|
||||||
|
{
|
||||||
|
this.processState.getValues().put(fieldName, value);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for values
|
** Setter for values
|
||||||
**
|
**
|
||||||
|
@ -61,6 +61,7 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi
|
|||||||
|
|
||||||
private QScheduleMetaData schedule;
|
private QScheduleMetaData schedule;
|
||||||
|
|
||||||
|
private Map<String, QSupplementalProcessMetaData> supplementalMetaData;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -544,4 +545,64 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi
|
|||||||
qInstance.addProcess(this);
|
qInstance.addProcess(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for supplementalMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, QSupplementalProcessMetaData> getSupplementalMetaData()
|
||||||
|
{
|
||||||
|
return (this.supplementalMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for supplementalMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public QSupplementalProcessMetaData getSupplementalMetaData(String type)
|
||||||
|
{
|
||||||
|
if(this.supplementalMetaData == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
return this.supplementalMetaData.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for supplementalMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setSupplementalMetaData(Map<String, QSupplementalProcessMetaData> supplementalMetaData)
|
||||||
|
{
|
||||||
|
this.supplementalMetaData = supplementalMetaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for supplementalMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public QProcessMetaData withSupplementalMetaData(Map<String, QSupplementalProcessMetaData> supplementalMetaData)
|
||||||
|
{
|
||||||
|
this.supplementalMetaData = supplementalMetaData;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for supplementalMetaData
|
||||||
|
*******************************************************************************/
|
||||||
|
public QProcessMetaData withSupplementalMetaData(QSupplementalProcessMetaData supplementalMetaData)
|
||||||
|
{
|
||||||
|
if(this.supplementalMetaData == null)
|
||||||
|
{
|
||||||
|
this.supplementalMetaData = new HashMap<>();
|
||||||
|
}
|
||||||
|
this.supplementalMetaData.put(supplementalMetaData.getType(), supplementalMetaData);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Base-class for process-level meta-data defined by some supplemental module, etc,
|
||||||
|
** outside of qqq core
|
||||||
|
*******************************************************************************/
|
||||||
|
public abstract class QSupplementalProcessMetaData
|
||||||
|
{
|
||||||
|
protected String type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for type
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return (this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for type
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setType(String type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for type
|
||||||
|
*******************************************************************************/
|
||||||
|
public QSupplementalProcessMetaData withType(String type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void enrich(QProcessMetaData process)
|
||||||
|
{
|
||||||
|
////////////////////////
|
||||||
|
// noop in base class //
|
||||||
|
////////////////////////
|
||||||
|
}
|
||||||
|
}
|
@ -30,14 +30,23 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import com.kingsrook.qqq.api.javalin.QBadRequestException;
|
import com.kingsrook.qqq.api.javalin.QBadRequestException;
|
||||||
import com.kingsrook.qqq.api.model.APIVersion;
|
import com.kingsrook.qqq.api.model.APIVersion;
|
||||||
|
import com.kingsrook.qqq.api.model.APIVersionRange;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiOperation;
|
import com.kingsrook.qqq.api.model.metadata.ApiOperation;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessCustomizers;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.PostRunApiProcessCustomizer;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.PreRunApiProcessCustomizer;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.permissions.TablePermissionSubType;
|
import com.kingsrook.qqq.backend.core.actions.permissions.TablePermissionSubType;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
@ -49,6 +58,8 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.logging.LogPair;
|
import com.kingsrook.qqq.backend.core.logging.LogPair;
|
||||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.QInputSource;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.QInputSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||||
@ -67,8 +78,10 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
|
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
|
||||||
import com.kingsrook.qqq.backend.core.model.statusmessages.NotFoundStatusMessage;
|
import com.kingsrook.qqq.backend.core.model.statusmessages.NotFoundStatusMessage;
|
||||||
@ -96,10 +109,11 @@ public class ApiImplementation
|
|||||||
{
|
{
|
||||||
private static final QLogger LOG = QLogger.getLogger(ApiImplementation.class);
|
private static final QLogger LOG = QLogger.getLogger(ApiImplementation.class);
|
||||||
|
|
||||||
/////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
// key: Pair<apiName, apiVersion> //
|
// key: Pair<apiName, apiVersion>, value: Map<name => metaData> //
|
||||||
/////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
private static Map<Pair<String, String>, Map<String, QTableMetaData>> tableApiNameMap = new HashMap<>();
|
private static Map<Pair<String, String>, Map<String, QTableMetaData>> tableApiNameMap = new HashMap<>();
|
||||||
|
private static Map<Pair<String, String>, Map<String, QProcessMetaData>> processApiNameMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -896,6 +910,99 @@ public class ApiImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static Map<String, Serializable> runProcess(ApiInstanceMetaData apiInstanceMetaData, String version, String processApiName, Map<String, String> paramMap) throws QException
|
||||||
|
{
|
||||||
|
QProcessMetaData process = validateProcessAndVersion(apiInstanceMetaData, version, processApiName);
|
||||||
|
String processName = process.getName();
|
||||||
|
ApiProcessMetaData apiProcessMetaData = getApiProcessMetaDataIfProcessIsInApi(apiInstanceMetaData, process);
|
||||||
|
|
||||||
|
List<String> badRequestMessages = new ArrayList<>();
|
||||||
|
Map<String, Serializable> output = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
String processUUID = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
RunProcessInput runProcessInput = new RunProcessInput();
|
||||||
|
runProcessInput.setProcessName(processName);
|
||||||
|
runProcessInput.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.SKIP);
|
||||||
|
runProcessInput.setProcessUUID(processUUID);
|
||||||
|
// todo i don't think runProcessInput.setCallback();
|
||||||
|
// todo i don't think runProcessInput.setAsyncJobCallback();
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// map input values //
|
||||||
|
//////////////////////
|
||||||
|
for(QFieldMetaData inputField : CollectionUtils.nonNullList(apiProcessMetaData.getInputFields()))
|
||||||
|
{
|
||||||
|
String value = paramMap.get(inputField.getName());
|
||||||
|
if(!StringUtils.hasContent(value) && inputField.getIsRequired())
|
||||||
|
{
|
||||||
|
badRequestMessages.add("Missing value for required input field " + inputField.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo - types?
|
||||||
|
|
||||||
|
runProcessInput.addValue(inputField.getName(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo! runProcessInput.setRecords(records);
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// throw if bad inputs have been noted //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
if(!badRequestMessages.isEmpty())
|
||||||
|
{
|
||||||
|
if(badRequestMessages.size() == 1)
|
||||||
|
{
|
||||||
|
throw (new QBadRequestException(badRequestMessages.get(0)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw (new QBadRequestException("Request failed with " + badRequestMessages.size() + " reasons: " + StringUtils.join(" \n", badRequestMessages)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// run pre-customizer, if there is one //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
Map<String, QCodeReference> customizers = apiProcessMetaData.getCustomizers();
|
||||||
|
if(customizers != null && customizers.containsKey(ApiProcessCustomizers.PRE_RUN.getRole()))
|
||||||
|
{
|
||||||
|
PreRunApiProcessCustomizer preRunCustomizer = QCodeLoader.getAdHoc(PreRunApiProcessCustomizer.class, customizers.get(ApiProcessCustomizers.PRE_RUN.getRole()));
|
||||||
|
preRunCustomizer.preApiRun(runProcessInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// run the process //
|
||||||
|
/////////////////////
|
||||||
|
RunProcessAction runProcessAction = new RunProcessAction();
|
||||||
|
RunProcessOutput runProcessOutput = runProcessAction.execute(runProcessInput);
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// run post-customizer, if there is one //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
if(customizers != null && customizers.containsKey(ApiProcessCustomizers.POST_RUN.getRole()))
|
||||||
|
{
|
||||||
|
PostRunApiProcessCustomizer postRunCustomizer = QCodeLoader.getAdHoc(PostRunApiProcessCustomizer.class, customizers.get(ApiProcessCustomizers.POST_RUN.getRole()));
|
||||||
|
postRunCustomizer.postApiRun(runProcessInput, runProcessOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// map output values //
|
||||||
|
///////////////////////
|
||||||
|
for(QFieldMetaData outputField : apiProcessMetaData.getOutputFields())
|
||||||
|
{
|
||||||
|
output.put(outputField.getName(), runProcessOutput.getValues().get(outputField.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -1078,14 +1185,14 @@ public class ApiImplementation
|
|||||||
ApiTableMetaDataContainer apiTableMetaDataContainer = ApiTableMetaDataContainer.of(table);
|
ApiTableMetaDataContainer apiTableMetaDataContainer = ApiTableMetaDataContainer.of(table);
|
||||||
if(apiTableMetaDataContainer == null)
|
if(apiTableMetaDataContainer == null)
|
||||||
{
|
{
|
||||||
LOG.info("404 because table apiMetaDataContainer is null", logPairs);
|
LOG.info("404 because table apiTableMetaDataContainer is null", logPairs);
|
||||||
throw (new QNotFoundException("Could not find a table named " + tableApiName + " in this api."));
|
throw (new QNotFoundException("Could not find a table named " + tableApiName + " in this api."));
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiTableMetaData apiTableMetaData = apiTableMetaDataContainer.getApiTableMetaData(apiInstanceMetaData.getName());
|
ApiTableMetaData apiTableMetaData = apiTableMetaDataContainer.getApiTableMetaData(apiInstanceMetaData.getName());
|
||||||
if(apiTableMetaData == null)
|
if(apiTableMetaData == null)
|
||||||
{
|
{
|
||||||
LOG.info("404 because table apiMetaData is null", logPairs);
|
LOG.info("404 because table apiTableMetaData is null", logPairs);
|
||||||
throw (new QNotFoundException("Could not find a table named " + tableApiName + " in this api."));
|
throw (new QNotFoundException("Could not find a table named " + tableApiName + " in this api."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1126,6 +1233,65 @@ public class ApiImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static QProcessMetaData validateProcessAndVersion(ApiInstanceMetaData apiInstanceMetaData, String version, String processApiName) throws QNotFoundException
|
||||||
|
{
|
||||||
|
QProcessMetaData process = getProcessByApiName(apiInstanceMetaData.getName(), version, processApiName);
|
||||||
|
LogPair[] logPairs = new LogPair[] { logPair("apiName", apiInstanceMetaData.getName()), logPair("version", version), logPair("processApiName", processApiName) };
|
||||||
|
|
||||||
|
if(process == null)
|
||||||
|
{
|
||||||
|
LOG.info("404 because process is null (processApiName=" + processApiName + ")", logPairs);
|
||||||
|
throw (new QNotFoundException("Could not find a process named " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BooleanUtils.isTrue(process.getIsHidden()))
|
||||||
|
{
|
||||||
|
LOG.info("404 because process isHidden", logPairs);
|
||||||
|
throw (new QNotFoundException("Could not find a process named " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiProcessMetaDataContainer apiProcessMetaDataContainer = ApiProcessMetaDataContainer.of(process);
|
||||||
|
if(apiProcessMetaDataContainer == null)
|
||||||
|
{
|
||||||
|
LOG.info("404 because process apiProcessMetaDataContainer is null", logPairs);
|
||||||
|
throw (new QNotFoundException("Could not find a process named " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiProcessMetaData apiProcessMetaData = apiProcessMetaDataContainer.getApiProcessMetaData(apiInstanceMetaData.getName());
|
||||||
|
if(apiProcessMetaData == null)
|
||||||
|
{
|
||||||
|
LOG.info("404 because process apiProcessMetaData is null", logPairs);
|
||||||
|
throw (new QNotFoundException("Could not find a process named " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BooleanUtils.isTrue(apiProcessMetaData.getIsExcluded()))
|
||||||
|
{
|
||||||
|
LOG.info("404 because process is excluded", logPairs);
|
||||||
|
throw (new QNotFoundException("Could not find a process named " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
APIVersion requestApiVersion = new APIVersion(version);
|
||||||
|
List<APIVersion> supportedVersions = apiInstanceMetaData.getSupportedVersions();
|
||||||
|
if(CollectionUtils.nullSafeIsEmpty(supportedVersions) || !supportedVersions.contains(requestApiVersion))
|
||||||
|
{
|
||||||
|
LOG.info("404 because requested version is not supported", logPairs);
|
||||||
|
throw (new QNotFoundException(version + " is not a supported version in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!apiProcessMetaData.getApiVersionRange().includes(requestApiVersion))
|
||||||
|
{
|
||||||
|
LOG.info("404 because process version range does not include requested version", logPairs);
|
||||||
|
throw (new QNotFoundException(version + " is not a supported version for process " + processApiName + " in this api."));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (process);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -1167,6 +1333,100 @@ public class ApiImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static QProcessMetaData getProcessByApiName(String apiName, String version, String processApiName)
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// processApiNameMap is a map of (apiName,apiVersion) => Map<String, QProcessMetaData>. //
|
||||||
|
// that is to say, a 2-level map. The first level is keyed by (apiName,apiVersion) pairs. //
|
||||||
|
// the second level is keyed by processApiNames. //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Pair<String, String> key = new Pair<>(apiName, version);
|
||||||
|
if(processApiNameMap.get(key) == null)
|
||||||
|
{
|
||||||
|
Map<String, QProcessMetaData> map = new HashMap<>();
|
||||||
|
|
||||||
|
for(QProcessMetaData process : QContext.getQInstance().getProcesses().values())
|
||||||
|
{
|
||||||
|
ApiProcessMetaDataContainer apiProcessMetaDataContainer = ApiProcessMetaDataContainer.of(process);
|
||||||
|
if(apiProcessMetaDataContainer != null)
|
||||||
|
{
|
||||||
|
ApiProcessMetaData apiProcessMetaData = apiProcessMetaDataContainer.getApiProcessMetaData(apiName);
|
||||||
|
if(apiProcessMetaData != null)
|
||||||
|
{
|
||||||
|
String name = process.getName();
|
||||||
|
if(StringUtils.hasContent(apiProcessMetaData.getApiProcessName()))
|
||||||
|
{
|
||||||
|
name = apiProcessMetaData.getApiProcessName();
|
||||||
|
}
|
||||||
|
map.put(name, process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processApiNameMap.put(key, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (processApiNameMap.get(key).get(processApiName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static ApiProcessMetaData getApiProcessMetaDataIfProcessIsInApi(ApiInstanceMetaData apiInstanceMetaData, QProcessMetaData process)
|
||||||
|
{
|
||||||
|
if(BooleanUtils.isTrue(process.getIsHidden()))
|
||||||
|
{
|
||||||
|
LOG.trace("excluding process because it is hidden (process=" + process.getName() + ")");
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiProcessMetaDataContainer apiProcessMetaDataContainer = ApiProcessMetaDataContainer.of(process);
|
||||||
|
if(apiProcessMetaDataContainer == null)
|
||||||
|
{
|
||||||
|
LOG.trace("excluding process because apiProcessMetaDataContainer is null (process=" + process.getName() + ")");
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiProcessMetaData apiProcessMetaData = apiProcessMetaDataContainer.getApiProcessMetaData(apiInstanceMetaData.getName());
|
||||||
|
if(apiProcessMetaData == null)
|
||||||
|
{
|
||||||
|
LOG.trace("excluding process because apiProcessMetaData is null (process=" + process.getName() + ")");
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BooleanUtils.isTrue(apiProcessMetaData.getIsExcluded()))
|
||||||
|
{
|
||||||
|
LOG.trace("excluding process because is excluded (process=" + process.getName() + ")");
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isProcessInAnySupportedVersions = false;
|
||||||
|
List<APIVersion> supportedVersions = apiInstanceMetaData.getSupportedVersions();
|
||||||
|
APIVersionRange apiVersionRange = apiProcessMetaData.getApiVersionRange();
|
||||||
|
for(APIVersion supportedVersion : supportedVersions)
|
||||||
|
{
|
||||||
|
if(apiVersionRange.includes(supportedVersion))
|
||||||
|
{
|
||||||
|
isProcessInAnySupportedVersions = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isProcessInAnySupportedVersions)
|
||||||
|
{
|
||||||
|
LOG.trace("excluding process because it is not in any supported versions (process=" + process.getName() + ")");
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (apiProcessMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -29,6 +29,7 @@ import java.time.Instant;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -43,8 +44,10 @@ import com.kingsrook.qqq.api.model.actions.GenerateOpenApiSpecOutput;
|
|||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataProvider;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataProvider;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.api.model.openapi.HttpMethod;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
@ -54,6 +57,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QPermissionDeniedException;
|
import com.kingsrook.qqq.backend.core.exceptions.QPermissionDeniedException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QRuntimeException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||||
@ -66,6 +70,8 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.authentication.Auth0AuthenticationMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.authentication.Auth0AuthenticationMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.branding.QBrandingMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.branding.QBrandingMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QUser;
|
import com.kingsrook.qqq.backend.core.model.session.QUser;
|
||||||
@ -156,10 +162,43 @@ public class QJavalinApiHandler
|
|||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
ApiBuilder.get("/", context -> doSpecHtml(context, apiInstanceMetaData));
|
ApiBuilder.get("/", context -> doSpecHtml(context, apiInstanceMetaData));
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// add known paths for specs & docs page //
|
||||||
|
///////////////////////////////////////////
|
||||||
ApiBuilder.get("/openapi.yaml", context -> doSpecYaml(context, apiInstanceMetaData));
|
ApiBuilder.get("/openapi.yaml", context -> doSpecYaml(context, apiInstanceMetaData));
|
||||||
ApiBuilder.get("/openapi.json", context -> doSpecJson(context, apiInstanceMetaData));
|
ApiBuilder.get("/openapi.json", context -> doSpecJson(context, apiInstanceMetaData));
|
||||||
ApiBuilder.get("/openapi.html", context -> doSpecHtml(context, apiInstanceMetaData));
|
ApiBuilder.get("/openapi.html", context -> doSpecHtml(context, apiInstanceMetaData));
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
// add processes //
|
||||||
|
///////////////////
|
||||||
|
for(QProcessMetaData process : qInstance.getProcesses().values())
|
||||||
|
{
|
||||||
|
ApiProcessMetaData apiProcessMetaData = ApiImplementation.getApiProcessMetaDataIfProcessIsInApi(apiInstanceMetaData, process);
|
||||||
|
if(apiProcessMetaData != null)
|
||||||
|
{
|
||||||
|
String path = getProcessApiPath(process, apiProcessMetaData, apiInstanceMetaData);
|
||||||
|
HttpMethod method = apiProcessMetaData.getMethod();
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case GET -> ApiBuilder.get(path, context -> runProcess(context, process, apiProcessMetaData, apiInstanceMetaData));
|
||||||
|
case POST -> ApiBuilder.post(path, context -> runProcess(context, process, apiProcessMetaData, apiInstanceMetaData));
|
||||||
|
case PUT -> ApiBuilder.put(path, context -> runProcess(context, process, apiProcessMetaData, apiInstanceMetaData));
|
||||||
|
case PATCH -> ApiBuilder.patch(path, context -> runProcess(context, process, apiProcessMetaData, apiInstanceMetaData));
|
||||||
|
case DELETE -> ApiBuilder.delete(path, context -> runProcess(context, process, apiProcessMetaData, apiInstanceMetaData));
|
||||||
|
default -> throw (new QRuntimeException("Unrecognized http method [" + method + "] for process [" + process.getName() + "]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doesProcessSupportAsync(apiInstanceMetaData, process))
|
||||||
|
{
|
||||||
|
ApiBuilder.get(path + "/status/{processId}", context -> getProcessStatus(context, apiInstanceMetaData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// add wildcard paths for tables //
|
||||||
|
///////////////////////////////////
|
||||||
ApiBuilder.path("/{tableName}", () ->
|
ApiBuilder.path("/{tableName}", () ->
|
||||||
{
|
{
|
||||||
ApiBuilder.get("/openapi.yaml", context -> doSpecYaml(context, apiInstanceMetaData));
|
ApiBuilder.get("/openapi.yaml", context -> doSpecYaml(context, apiInstanceMetaData));
|
||||||
@ -208,6 +247,104 @@ public class QJavalinApiHandler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void getProcessStatus(Context context, ApiInstanceMetaData apiInstanceMetaData)
|
||||||
|
{
|
||||||
|
// todo!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@SuppressWarnings("checkstyle:indentation")
|
||||||
|
private void runProcess(Context context, QProcessMetaData processMetaData, ApiProcessMetaData apiProcessMetaData, ApiInstanceMetaData apiInstanceMetaData)
|
||||||
|
{
|
||||||
|
String version = context.pathParam("version");
|
||||||
|
APILog apiLog = newAPILog(context);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
setupSession(context, null, version, apiInstanceMetaData);
|
||||||
|
QJavalinAccessLogger.logStart("apiRunProcess", logPair("process", processMetaData.getName()));
|
||||||
|
|
||||||
|
Map<String, String> parameters = new LinkedHashMap<>();
|
||||||
|
for(QFieldMetaData inputField : CollectionUtils.nonNullList(apiProcessMetaData.getInputFields()))
|
||||||
|
{
|
||||||
|
String value = switch(apiProcessMetaData.getMethod())
|
||||||
|
{
|
||||||
|
case GET -> context.queryParam(inputField.getName());
|
||||||
|
// todo - other methods (all from a JSON body??)
|
||||||
|
default -> throw new QException("Http method " + apiLog.getMethod() + " is not yet implemented for reading parameters");
|
||||||
|
};
|
||||||
|
parameters.put(inputField.getName(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Serializable> outputRecord = ApiImplementation.runProcess(apiInstanceMetaData, version, apiProcessMetaData.getApiProcessName(), parameters);
|
||||||
|
|
||||||
|
QJavalinAccessLogger.logEndSuccess();
|
||||||
|
String resultString = toJson(outputRecord);
|
||||||
|
context.result(resultString);
|
||||||
|
storeApiLog(apiLog.withStatusCode(context.statusCode()).withResponseBody(resultString));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
QJavalinAccessLogger.logEndFail(e);
|
||||||
|
handleException(context, e, apiLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private boolean doesProcessSupportAsync(ApiInstanceMetaData apiInstanceMetaData, QProcessMetaData process)
|
||||||
|
{
|
||||||
|
// todo - implement
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private String getProcessApiPath(QProcessMetaData process, ApiProcessMetaData apiProcessMetaData, ApiInstanceMetaData apiInstanceMetaData)
|
||||||
|
{
|
||||||
|
if(StringUtils.hasContent(apiProcessMetaData.getPath()))
|
||||||
|
{
|
||||||
|
return apiProcessMetaData.getPath() + "/" + apiProcessMetaData.getApiProcessName();
|
||||||
|
}
|
||||||
|
else if(StringUtils.hasContent(process.getTableName()))
|
||||||
|
{
|
||||||
|
QTableMetaData table = qInstance.getTable(process.getTableName());
|
||||||
|
String tablePathPart = table.getName();
|
||||||
|
ApiTableMetaDataContainer apiTableMetaDataContainer = ApiTableMetaDataContainer.of(table);
|
||||||
|
if(apiTableMetaDataContainer != null)
|
||||||
|
{
|
||||||
|
ApiTableMetaData apiTableMetaData = apiTableMetaDataContainer.getApis().get(apiInstanceMetaData.getName());
|
||||||
|
if(apiTableMetaData != null)
|
||||||
|
{
|
||||||
|
if(StringUtils.hasContent(apiTableMetaData.getApiTableName()))
|
||||||
|
{
|
||||||
|
tablePathPart = apiTableMetaData.getApiTableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tablePathPart + "/" + apiProcessMetaData.getApiProcessName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return apiProcessMetaData.getApiProcessName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.api.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public enum ApiProcessCustomizers
|
||||||
|
{
|
||||||
|
PRE_RUN("preRun", PreRunApiProcessCustomizer.class),
|
||||||
|
POST_RUN("postRun", PreRunApiProcessCustomizer.class);
|
||||||
|
|
||||||
|
private final String role;
|
||||||
|
private final Class<?> expectedType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
ApiProcessCustomizers(String role, Class<?> expectedType)
|
||||||
|
{
|
||||||
|
this.role = role;
|
||||||
|
this.expectedType = expectedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Get the FilesystemTableCustomer for a given role (e.g., the role used in meta-data, not
|
||||||
|
** the enum-constant name).
|
||||||
|
*******************************************************************************/
|
||||||
|
public static ApiProcessCustomizers forRole(String name)
|
||||||
|
{
|
||||||
|
for(ApiProcessCustomizers value : values())
|
||||||
|
{
|
||||||
|
if(value.role.equals(name))
|
||||||
|
{
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for role
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getRole()
|
||||||
|
{
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for expectedType
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Class<?> getExpectedType()
|
||||||
|
{
|
||||||
|
return expectedType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,496 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.api.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.api.ApiSupplementType;
|
||||||
|
import com.kingsrook.qqq.api.model.APIVersionRange;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.api.model.openapi.HttpMethod;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ApiProcessMetaData
|
||||||
|
{
|
||||||
|
private String initialVersion;
|
||||||
|
private String finalVersion;
|
||||||
|
|
||||||
|
private String apiProcessName;
|
||||||
|
private Boolean isExcluded;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
private HttpMethod method;
|
||||||
|
|
||||||
|
private List<QFieldMetaData> inputFields;
|
||||||
|
private List<QFieldMetaData> outputFields;
|
||||||
|
|
||||||
|
private Map<String, QCodeReference> customizers;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withInferredInputFields(QProcessMetaData processMetaData)
|
||||||
|
{
|
||||||
|
inputFields = new ArrayList<>();
|
||||||
|
for(QStepMetaData stepMetaData : CollectionUtils.nonNullList(processMetaData.getStepList()))
|
||||||
|
{
|
||||||
|
if(stepMetaData instanceof QFrontendStepMetaData frontendStep)
|
||||||
|
{
|
||||||
|
inputFields.addAll(frontendStep.getInputFields());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withInferredOutputFields(QProcessMetaData processMetaData)
|
||||||
|
{
|
||||||
|
outputFields = new ArrayList<>();
|
||||||
|
for(QStepMetaData stepMetaData : CollectionUtils.nonNullList(processMetaData.getStepList()))
|
||||||
|
{
|
||||||
|
if(stepMetaData instanceof QFrontendStepMetaData frontendStep)
|
||||||
|
{
|
||||||
|
outputFields.addAll(frontendStep.getOutputFields());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public APIVersionRange getApiVersionRange()
|
||||||
|
{
|
||||||
|
if(getInitialVersion() == null)
|
||||||
|
{
|
||||||
|
return APIVersionRange.none();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (getFinalVersion() != null
|
||||||
|
? APIVersionRange.betweenAndIncluding(getInitialVersion(), getFinalVersion())
|
||||||
|
: APIVersionRange.afterAndIncluding(getInitialVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void enrich(String apiName, QProcessMetaData process)
|
||||||
|
{
|
||||||
|
if(!StringUtils.hasContent(getApiProcessName()))
|
||||||
|
{
|
||||||
|
setApiProcessName(process.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(initialVersion != null)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// make sure all fields have at least an initial version set //
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
for(QFieldMetaData field : CollectionUtils.mergeLists(getInputFields(), getOutputFields()))
|
||||||
|
{
|
||||||
|
ApiFieldMetaData apiFieldMetaData = ensureFieldHasApiSupplementalMetaData(apiName, field);
|
||||||
|
if(apiFieldMetaData.getInitialVersion() == null)
|
||||||
|
{
|
||||||
|
apiFieldMetaData.setInitialVersion(initialVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static ApiFieldMetaData ensureFieldHasApiSupplementalMetaData(String apiName, QFieldMetaData field)
|
||||||
|
{
|
||||||
|
if(field.getSupplementalMetaData(ApiSupplementType.NAME) == null)
|
||||||
|
{
|
||||||
|
field.withSupplementalMetaData(new ApiFieldMetaDataContainer());
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiFieldMetaDataContainer apiFieldMetaDataContainer = ApiFieldMetaDataContainer.of(field);
|
||||||
|
if(apiFieldMetaDataContainer.getApiFieldMetaData(apiName) == null)
|
||||||
|
{
|
||||||
|
apiFieldMetaDataContainer.withApiFieldMetaData(apiName, new ApiFieldMetaData());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (apiFieldMetaDataContainer.getApiFieldMetaData(apiName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for a single outputField
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withOutputField(QFieldMetaData outputField)
|
||||||
|
{
|
||||||
|
if(this.outputFields == null)
|
||||||
|
{
|
||||||
|
this.outputFields = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.outputFields.add(outputField);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for a single inputField
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withInputField(QFieldMetaData inputField)
|
||||||
|
{
|
||||||
|
if(this.inputFields == null)
|
||||||
|
{
|
||||||
|
this.inputFields = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.inputFields.add(inputField);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for initialVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getInitialVersion()
|
||||||
|
{
|
||||||
|
return (this.initialVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for initialVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setInitialVersion(String initialVersion)
|
||||||
|
{
|
||||||
|
this.initialVersion = initialVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for initialVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withInitialVersion(String initialVersion)
|
||||||
|
{
|
||||||
|
this.initialVersion = initialVersion;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for finalVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getFinalVersion()
|
||||||
|
{
|
||||||
|
return (this.finalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for finalVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setFinalVersion(String finalVersion)
|
||||||
|
{
|
||||||
|
this.finalVersion = finalVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for finalVersion
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withFinalVersion(String finalVersion)
|
||||||
|
{
|
||||||
|
this.finalVersion = finalVersion;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apiProcessName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getApiProcessName()
|
||||||
|
{
|
||||||
|
return (this.apiProcessName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apiProcessName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApiProcessName(String apiProcessName)
|
||||||
|
{
|
||||||
|
this.apiProcessName = apiProcessName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for apiProcessName
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withApiProcessName(String apiProcessName)
|
||||||
|
{
|
||||||
|
this.apiProcessName = apiProcessName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for isExcluded
|
||||||
|
*******************************************************************************/
|
||||||
|
public Boolean getIsExcluded()
|
||||||
|
{
|
||||||
|
return (this.isExcluded);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for isExcluded
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIsExcluded(Boolean isExcluded)
|
||||||
|
{
|
||||||
|
this.isExcluded = isExcluded;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for isExcluded
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withIsExcluded(Boolean isExcluded)
|
||||||
|
{
|
||||||
|
this.isExcluded = isExcluded;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for method
|
||||||
|
*******************************************************************************/
|
||||||
|
public HttpMethod getMethod()
|
||||||
|
{
|
||||||
|
return (this.method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for method
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setMethod(HttpMethod method)
|
||||||
|
{
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for method
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withMethod(HttpMethod method)
|
||||||
|
{
|
||||||
|
this.method = method;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for path
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getPath()
|
||||||
|
{
|
||||||
|
return (this.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for path
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setPath(String path)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for path
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withPath(String path)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for inputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QFieldMetaData> getInputFields()
|
||||||
|
{
|
||||||
|
return (this.inputFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for inputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setInputFields(List<QFieldMetaData> inputFields)
|
||||||
|
{
|
||||||
|
this.inputFields = inputFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for inputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withInputFields(List<QFieldMetaData> inputFields)
|
||||||
|
{
|
||||||
|
this.inputFields = inputFields;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for outputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QFieldMetaData> getOutputFields()
|
||||||
|
{
|
||||||
|
return (this.outputFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for outputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setOutputFields(List<QFieldMetaData> outputFields)
|
||||||
|
{
|
||||||
|
this.outputFields = outputFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for outputFields
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withOutputFields(List<QFieldMetaData> outputFields)
|
||||||
|
{
|
||||||
|
this.outputFields = outputFields;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for customizers
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, QCodeReference> getCustomizers()
|
||||||
|
{
|
||||||
|
return (this.customizers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for customizers
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setCustomizers(Map<String, QCodeReference> customizers)
|
||||||
|
{
|
||||||
|
this.customizers = customizers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for customizers
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withCustomizers(Map<String, QCodeReference> customizers)
|
||||||
|
{
|
||||||
|
this.customizers = customizers;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData withCustomizer(String role, QCodeReference customizer)
|
||||||
|
{
|
||||||
|
if(this.customizers == null)
|
||||||
|
{
|
||||||
|
this.customizers = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.customizers.containsKey(role))
|
||||||
|
{
|
||||||
|
throw (new IllegalArgumentException("Attempt to add a second customizer with role [" + role + "] to apiProcess [" + apiProcessName + "]."));
|
||||||
|
}
|
||||||
|
this.customizers.put(role, customizer);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.api.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.api.ApiSupplementType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QSupplementalProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ApiProcessMetaDataContainer extends QSupplementalProcessMetaData
|
||||||
|
{
|
||||||
|
private Map<String, ApiProcessMetaData> apis;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaDataContainer()
|
||||||
|
{
|
||||||
|
setType("api");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static ApiProcessMetaDataContainer of(QProcessMetaData process)
|
||||||
|
{
|
||||||
|
return ((ApiProcessMetaDataContainer) process.getSupplementalMetaData(ApiSupplementType.NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void enrich(QProcessMetaData process)
|
||||||
|
{
|
||||||
|
super.enrich(process);
|
||||||
|
|
||||||
|
for(Map.Entry<String, ApiProcessMetaData> entry : CollectionUtils.nonNullMap(apis).entrySet())
|
||||||
|
{
|
||||||
|
entry.getValue().enrich(entry.getKey(), process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apis
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, ApiProcessMetaData> getApis()
|
||||||
|
{
|
||||||
|
return (this.apis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apis
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaData getApiProcessMetaData(String apiName)
|
||||||
|
{
|
||||||
|
if(this.apis == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this.apis.get(apiName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apis
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApis(Map<String, ApiProcessMetaData> apis)
|
||||||
|
{
|
||||||
|
this.apis = apis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for apis
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaDataContainer withApis(Map<String, ApiProcessMetaData> apis)
|
||||||
|
{
|
||||||
|
this.apis = apis;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for apis
|
||||||
|
*******************************************************************************/
|
||||||
|
public ApiProcessMetaDataContainer withApiProcessMetaData(String apiName, ApiProcessMetaData apiProcessMetaData)
|
||||||
|
{
|
||||||
|
if(this.apis == null)
|
||||||
|
{
|
||||||
|
this.apis = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
this.apis.put(apiName, apiProcessMetaData);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.kingsrook.qqq.api.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface PostRunApiProcessCustomizer
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void postApiRun(RunProcessInput runProcessInput, RunProcessOutput runProcessOutput) throws QException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.kingsrook.qqq.api.model.metadata.processes;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface PreRunApiProcessCustomizer
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void preApiRun(RunProcessInput runProcessInput) throws QException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.kingsrook.qqq.api.model.openapi;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public enum HttpMethod
|
||||||
|
{
|
||||||
|
GET,
|
||||||
|
POST,
|
||||||
|
PUT,
|
||||||
|
PATCH,
|
||||||
|
DELETE
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.kingsrook.qqq.api;
|
||||||
|
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class GetPersonInfoStep implements BackendStep
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
runBackendStepOutput.addValue("density", new BigDecimal("3.50"));
|
||||||
|
runBackendStepOutput.addValue("daysOld", runBackendStepInput.getValueInteger("age") * 365);
|
||||||
|
runBackendStepOutput.addValue("nickname", "Guy from " + runBackendStepInput.getValueString("homeTown"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,8 +29,11 @@ import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
|||||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaDataContainer;
|
||||||
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaData;
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.api.model.metadata.processes.ApiProcessMetaDataContainer;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaDataContainer;
|
||||||
|
import com.kingsrook.qqq.api.model.openapi.HttpMethod;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreDeleteCustomizer;
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreDeleteCustomizer;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreInsertCustomizer;
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreInsertCustomizer;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreUpdateCustomizer;
|
import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPreUpdateCustomizer;
|
||||||
@ -45,12 +48,23 @@ import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.authentication.Auth0AuthenticationMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.authentication.Auth0AuthenticationMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode.HtmlWrapper;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode.WidgetHtmlLine;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
|
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinType;
|
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PVSValueFormatAndFields;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.NoCodeWidgetFrontendComponentMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponentMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
|
||||||
@ -59,6 +73,7 @@ import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
|
|||||||
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
|
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
|
||||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
|
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -74,6 +89,8 @@ public class TestUtils
|
|||||||
public static final String TABLE_NAME_LINE_ITEM_EXTRINSIC = "orderLineExtrinsic";
|
public static final String TABLE_NAME_LINE_ITEM_EXTRINSIC = "orderLineExtrinsic";
|
||||||
public static final String TABLE_NAME_ORDER_EXTRINSIC = "orderExtrinsic";
|
public static final String TABLE_NAME_ORDER_EXTRINSIC = "orderExtrinsic";
|
||||||
|
|
||||||
|
public static final String PROCESS_NAME_GET_PERSON_INFO = "getPersonInfo";
|
||||||
|
|
||||||
public static final String API_NAME = "test-api";
|
public static final String API_NAME = "test-api";
|
||||||
public static final String ALTERNATIVE_API_NAME = "person-api";
|
public static final String ALTERNATIVE_API_NAME = "person-api";
|
||||||
|
|
||||||
@ -103,6 +120,9 @@ public class TestUtils
|
|||||||
qInstance.addJoin(defineJoinLineItemLineItemExtrinsic());
|
qInstance.addJoin(defineJoinLineItemLineItemExtrinsic());
|
||||||
qInstance.addJoin(defineJoinOrderOrderExtrinsic());
|
qInstance.addJoin(defineJoinOrderOrderExtrinsic());
|
||||||
|
|
||||||
|
qInstance.addPossibleValueSource(definePersonPossibleValueSource());
|
||||||
|
qInstance.addProcess(defineProcessGetPersonInfo());
|
||||||
|
|
||||||
qInstance.setAuthentication(new Auth0AuthenticationMetaData().withType(QAuthenticationType.FULLY_ANONYMOUS).withName("anonymous"));
|
qInstance.setAuthentication(new Auth0AuthenticationMetaData().withType(QAuthenticationType.FULLY_ANONYMOUS).withName("anonymous"));
|
||||||
|
|
||||||
qInstance.withSupplementalMetaData(new ApiInstanceMetaDataContainer()
|
qInstance.withSupplementalMetaData(new ApiInstanceMetaDataContainer()
|
||||||
@ -133,6 +153,80 @@ public class TestUtils
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static QPossibleValueSource definePersonPossibleValueSource()
|
||||||
|
{
|
||||||
|
return new QPossibleValueSource()
|
||||||
|
.withName(TABLE_NAME_PERSON)
|
||||||
|
.withType(QPossibleValueSourceType.TABLE)
|
||||||
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
|
.withValueFormatAndFields(PVSValueFormatAndFields.LABEL_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static QProcessMetaData defineProcessGetPersonInfo()
|
||||||
|
{
|
||||||
|
QProcessMetaData process = new QProcessMetaData()
|
||||||
|
.withName(PROCESS_NAME_GET_PERSON_INFO)
|
||||||
|
.withLabel("Get Person Info")
|
||||||
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
|
.addStep(new QFrontendStepMetaData()
|
||||||
|
.withName("enterInputs")
|
||||||
|
.withLabel("Person Info Input")
|
||||||
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM))
|
||||||
|
|
||||||
|
.withFormField(new QFieldMetaData("age", QFieldType.INTEGER))
|
||||||
|
.withFormField(new QFieldMetaData("partnerPersonId", QFieldType.INTEGER).withPossibleValueSourceName(TABLE_NAME_PERSON))
|
||||||
|
.withFormField(new QFieldMetaData("heightInches", QFieldType.DECIMAL))
|
||||||
|
.withFormField(new QFieldMetaData("weightPounds", QFieldType.INTEGER))
|
||||||
|
.withFormField(new QFieldMetaData("homeTown", QFieldType.STRING))
|
||||||
|
|
||||||
|
.withComponent(new NoCodeWidgetFrontendComponentMetaData()
|
||||||
|
|
||||||
|
.withOutput(new WidgetHtmlLine()
|
||||||
|
.withWrapper(HtmlWrapper.divWithStyles(HtmlWrapper.STYLE_FLOAT_RIGHT, HtmlWrapper.STYLE_MEDIUM_CENTERED, HtmlWrapper.styleWidth("50%")))
|
||||||
|
.withVelocityTemplate("""
|
||||||
|
<b>Density:</b><br />$density<br/>
|
||||||
|
"""))
|
||||||
|
|
||||||
|
.withOutput(new WidgetHtmlLine()
|
||||||
|
.withVelocityTemplate("""
|
||||||
|
<b>Days old:</b> $daysOld<br/>
|
||||||
|
<b>Nickname:</b> $nickname<br/>
|
||||||
|
"""))
|
||||||
|
))
|
||||||
|
|
||||||
|
.addStep(new QBackendStepMetaData()
|
||||||
|
.withName("execute")
|
||||||
|
.withCode(new QCodeReference(GetPersonInfoStep.class)))
|
||||||
|
|
||||||
|
.addStep(new QFrontendStepMetaData()
|
||||||
|
.withName("dummyStep")
|
||||||
|
);
|
||||||
|
|
||||||
|
process.withSupplementalMetaData(new ApiProcessMetaDataContainer()
|
||||||
|
.withApiProcessMetaData(API_NAME, new ApiProcessMetaData()
|
||||||
|
.withInitialVersion(CURRENT_API_VERSION)
|
||||||
|
.withMethod(HttpMethod.GET)
|
||||||
|
.withInferredInputFields(process)
|
||||||
|
.withOutputFields(ListBuilder.of(
|
||||||
|
new QFieldMetaData("density", QFieldType.DECIMAL),
|
||||||
|
new QFieldMetaData("daysOld", QFieldType.INTEGER),
|
||||||
|
new QFieldMetaData("nickname", QFieldType.STRING)
|
||||||
|
))
|
||||||
|
));
|
||||||
|
|
||||||
|
return (process);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Define the in-memory backend used in standard tests
|
** Define the in-memory backend used in standard tests
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -1439,6 +1439,20 @@ class QJavalinApiHandlerTest extends BaseTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testProcess() throws QException
|
||||||
|
{
|
||||||
|
HttpResponse<String> response = Unirest.get(BASE_URL + "/api/" + VERSION + "/person/getPersonInfo?age=43&partnerPersonId=1&heightInches=72&weightPounds=220&homeTown=Chester").asString();
|
||||||
|
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
JSONObject jsonObject = new JSONObject(response.getBody());
|
||||||
|
System.out.println(jsonObject.toString(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
Reference in New Issue
Block a user