Adding POST_QUERY_RECORD customizer; formalizing customizers a bit more

This commit is contained in:
2022-08-12 11:39:39 -05:00
parent 965bc5bf29
commit 52121cc4f3
12 changed files with 378 additions and 45 deletions

View File

@ -0,0 +1,96 @@
/*
* 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.backend.core.actions.customizers;
import java.util.Optional;
import java.util.function.Function;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/*******************************************************************************
** Utility to load code for running QQQ customizers.
*******************************************************************************/
public class CustomizerLoader
{
private static final Logger LOG = LogManager.getLogger(CustomizerLoader.class);
/*******************************************************************************
**
*******************************************************************************/
public static Function<?, ?> getTableCustomizerFunction(QTableMetaData table, String customizerName)
{
Optional<QCodeReference> codeReference = table.getCustomizer(customizerName);
if(codeReference.isPresent())
{
return (CustomizerLoader.getFunction(codeReference.get()));
}
return null;
}
/*******************************************************************************
**
*******************************************************************************/
@SuppressWarnings("unchecked")
public static <T, R> Function<T, R> getFunction(QCodeReference codeReference)
{
if(codeReference == null)
{
return (null);
}
if(!codeReference.getCodeType().equals(QCodeType.JAVA))
{
///////////////////////////////////////////////////////////////////////////////////////
// todo - 1) support more languages, 2) wrap them w/ java Functions here, 3) profit! //
///////////////////////////////////////////////////////////////////////////////////////
throw (new IllegalArgumentException("Only JAVA customizers are supported at this time."));
}
try
{
Class<?> customizerClass = Class.forName(codeReference.getName());
return ((Function<T, R>) customizerClass.getConstructor().newInstance());
}
catch(Exception e)
{
LOG.error("Error initializing customizer: " + codeReference);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// return null here - under the assumption that during normal run-time operations, we'll never hit here //
// as we'll want to validate all functions in the instance validator at startup time (and IT will throw //
// if it finds an invalid code reference //
//////////////////////////////////////////////////////////////////////////////////////////////////////////
return (null);
}
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.backend.core.actions.customizers;
/*******************************************************************************
** Standard place where the names of QQQ Customization points are defined.
*******************************************************************************/
public interface Customizers
{
String POST_QUERY_RECORD = "postQueryRecord";
}

View File

@ -57,7 +57,7 @@ public class QInstanceValidationException extends QException
{
super(
(reasons != null && reasons.size() > 0)
? "Instance validation failed for the following reasons: " + StringUtils.joinWithCommasAndAnd(reasons)
? "Instance validation failed for the following reasons:\n - " + StringUtils.join("\n - ", reasons)
: "Validation failed, but no reasons were provided");
if(reasons != null && reasons.size() > 0)

View File

@ -24,8 +24,13 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.query;
import java.io.Serializable;
import java.util.List;
import java.util.function.Function;
import com.kingsrook.qqq.backend.core.actions.customizers.CustomizerLoader;
import com.kingsrook.qqq.backend.core.actions.customizers.Customizers;
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/*******************************************************************************
@ -34,8 +39,12 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
*******************************************************************************/
public class QueryOutput extends AbstractActionOutput implements Serializable
{
private static final Logger LOG = LogManager.getLogger(QueryOutput.class);
private QueryOutputStorageInterface storage;
private Function<QRecord, QRecord> postQueryRecordCustomizer;
/*******************************************************************************
@ -52,6 +61,8 @@ public class QueryOutput extends AbstractActionOutput implements Serializable
{
storage = new QueryOutputList();
}
postQueryRecordCustomizer = (Function<QRecord, QRecord>) CustomizerLoader.getTableCustomizerFunction(queryInput.getTable(), Customizers.POST_QUERY_RECORD);
}
@ -65,16 +76,36 @@ public class QueryOutput extends AbstractActionOutput implements Serializable
*******************************************************************************/
public void addRecord(QRecord record)
{
record = runPostQueryRecordCustomizer(record);
storage.addRecord(record);
}
/*******************************************************************************
**
*******************************************************************************/
public QRecord runPostQueryRecordCustomizer(QRecord record)
{
if(this.postQueryRecordCustomizer != null)
{
record = this.postQueryRecordCustomizer.apply(record);
}
return record;
}
/*******************************************************************************
** add a list of records to this output
*******************************************************************************/
public void addRecords(List<QRecord> records)
{
if(this.postQueryRecordCustomizer != null)
{
records.replaceAll(t -> this.postQueryRecordCustomizer.apply(t));
}
storage.addRecords(records);
}

View File

@ -408,12 +408,7 @@ public class QTableMetaData implements QAppChildMetaData, Serializable
}
QCodeReference function = customizers.get(customizerName);
if(function == null)
{
throw (new IllegalArgumentException("Customizer [" + customizerName + "] was not found in table [" + name + "]."));
}
return (Optional.of(function));
return (Optional.ofNullable(function));
}