mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
New version of interface for QBitMetaData production
This commit is contained in:
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2025. 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.qbits;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QRuntimeException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerHelper;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerInterface;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerMultiOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** 2nd generation interface for top-level meta-data production classes that make
|
||||
** a qbit (evolution over QBitProducer).
|
||||
**
|
||||
*******************************************************************************/
|
||||
public interface QBitMetaDataProducer<C extends QBitConfig> extends MetaDataProducerInterface<MetaDataProducerMultiOutput>
|
||||
{
|
||||
QLogger LOG = QLogger.getLogger(QBitMetaDataProducer.class);
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
C getQBitConfig();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
QBitMetaData getQBitMetaData();
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
default String getNamespace()
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
default void postProduceActions(MetaDataProducerMultiOutput metaDataProducerMultiOutput, QInstance qinstance)
|
||||
{
|
||||
/////////////////////
|
||||
// noop by default //
|
||||
/////////////////////
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
default String getPackageNameForFindingMetaDataProducers()
|
||||
{
|
||||
Class<?> clazz = getClass();
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Walk up the hierarchy until we find the direct implementer //
|
||||
////////////////////////////////////////////////////////////////
|
||||
while(clazz != null)
|
||||
{
|
||||
Class<?>[] interfaces = clazz.getInterfaces();
|
||||
for(Class<?> interfaze : interfaces)
|
||||
{
|
||||
if(interfaze == QBitMetaDataProducer.class)
|
||||
{
|
||||
return clazz.getPackageName();
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
|
||||
throw (new QRuntimeException("Unable to find packageName for QBitMetaDataProducer. You may need to implement getPackageName yourself..."));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
default MetaDataProducerMultiOutput produce(QInstance qInstance) throws QException
|
||||
{
|
||||
MetaDataProducerMultiOutput rs = new MetaDataProducerMultiOutput();
|
||||
|
||||
QBitMetaData qBitMetaData = getQBitMetaData();
|
||||
C qBitConfig = getQBitConfig();
|
||||
|
||||
qInstance.addQBit(qBitMetaData);
|
||||
|
||||
QBitProductionContext.pushQBitConfig(qBitConfig);
|
||||
QBitProductionContext.pushMetaDataProducerMultiOutput(rs);
|
||||
|
||||
try
|
||||
{
|
||||
qBitConfig.validate(qInstance);
|
||||
|
||||
List<MetaDataProducerInterface<?>> producers = MetaDataProducerHelper.findProducers(getPackageNameForFindingMetaDataProducers());
|
||||
MetaDataProducerHelper.sortMetaDataProducers(producers);
|
||||
for(MetaDataProducerInterface<?> producer : producers)
|
||||
{
|
||||
if(producer.getClass().equals(this.getClass()))
|
||||
{
|
||||
/////////////////////////////////////////////
|
||||
// avoid recursive processing of ourselves //
|
||||
/////////////////////////////////////////////
|
||||
continue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// todo is this deprecated in favor of QBitProductionContext's stack... ? //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if(producer instanceof QBitComponentMetaDataProducer<?, ?>)
|
||||
{
|
||||
QBitComponentMetaDataProducer<?, C> qBitComponentMetaDataProducer = (QBitComponentMetaDataProducer<?, C>) producer;
|
||||
qBitComponentMetaDataProducer.setQBitConfig(qBitConfig);
|
||||
}
|
||||
|
||||
if(!producer.isEnabled())
|
||||
{
|
||||
LOG.debug("Not using producer which is not enabled", logPair("producer", producer.getClass().getSimpleName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
MetaDataProducerOutput subProducerOutput = producer.produce(qInstance);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// apply some things from the config to tables //
|
||||
/////////////////////////////////////////////////
|
||||
if(subProducerOutput instanceof QTableMetaData table)
|
||||
{
|
||||
if(qBitConfig.getTableMetaDataCustomizer() != null)
|
||||
{
|
||||
subProducerOutput = qBitConfig.getTableMetaDataCustomizer().customizeMetaData(qInstance, table);
|
||||
}
|
||||
|
||||
if(!StringUtils.hasContent(table.getBackendName()) && StringUtils.hasContent(qBitConfig.getDefaultBackendNameForTables()))
|
||||
{
|
||||
table.setBackendName(qBitConfig.getDefaultBackendNameForTables());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// set source qbit, if subProducerOutput is aware of such //
|
||||
////////////////////////////////////////////////////////////
|
||||
if(subProducerOutput instanceof SourceQBitAware sourceQBitAware)
|
||||
{
|
||||
sourceQBitAware.setSourceQBitName(qBitMetaData.getName());
|
||||
}
|
||||
|
||||
rs.add(subProducerOutput);
|
||||
}
|
||||
|
||||
postProduceActions(rs, qInstance);
|
||||
|
||||
return (rs);
|
||||
}
|
||||
finally
|
||||
{
|
||||
QBitProductionContext.popQBitConfig();
|
||||
QBitProductionContext.popMetaDataProducerMultiOutput();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -76,9 +76,6 @@ public interface QBitProducer
|
||||
{
|
||||
qBitConfig.validate(qInstance);
|
||||
|
||||
///////////////////////////////
|
||||
// todo - move to base class //
|
||||
///////////////////////////////
|
||||
for(MetaDataProducerInterface<?> producer : producers)
|
||||
{
|
||||
if(producer instanceof QBitComponentMetaDataProducer<?, ?>)
|
||||
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2025. 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.qbits;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerMultiOutput;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** While a qbit is being produced, track the context of the current config
|
||||
** and metaDataProducerMultiOutput that is being used. also, in case one
|
||||
** qbit produces another, push these contextual objects on a stack.
|
||||
*******************************************************************************/
|
||||
public class QBitProductionContext
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(QBitProductionContext.class);
|
||||
|
||||
private static Stack<QBitConfig> qbitConfigStack = new Stack<>();
|
||||
private static Stack<MetaDataProducerMultiOutput> metaDataProducerMultiOutputStack = new Stack<>();
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static void pushQBitConfig(QBitConfig qBitConfig)
|
||||
{
|
||||
qbitConfigStack.push(qBitConfig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static QBitConfig peekQBitConfig()
|
||||
{
|
||||
if(qbitConfigStack.isEmpty())
|
||||
{
|
||||
LOG.warn("Request to peek at empty QBitProductionContext configStack - returning null");
|
||||
return (null);
|
||||
}
|
||||
return qbitConfigStack.peek();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static void popQBitConfig()
|
||||
{
|
||||
if(qbitConfigStack.isEmpty())
|
||||
{
|
||||
LOG.warn("Request to pop empty QBitProductionContext configStack - returning with noop");
|
||||
return;
|
||||
}
|
||||
|
||||
qbitConfigStack.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static void pushMetaDataProducerMultiOutput(MetaDataProducerMultiOutput metaDataProducerMultiOutput)
|
||||
{
|
||||
metaDataProducerMultiOutputStack.push(metaDataProducerMultiOutput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static MetaDataProducerMultiOutput peekMetaDataProducerMultiOutput()
|
||||
{
|
||||
if(metaDataProducerMultiOutputStack.isEmpty())
|
||||
{
|
||||
LOG.warn("Request to peek at empty QBitProductionContext configStack - returning null");
|
||||
return (null);
|
||||
}
|
||||
return metaDataProducerMultiOutputStack.peek();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static List<MetaDataProducerMultiOutput> getReadOnlyViewOfMetaDataProducerMultiOutputStack()
|
||||
{
|
||||
return Collections.unmodifiableList(metaDataProducerMultiOutputStack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static void popMetaDataProducerMultiOutput()
|
||||
{
|
||||
if(metaDataProducerMultiOutputStack.isEmpty())
|
||||
{
|
||||
LOG.warn("Request to pop empty QBitProductionContext metaDataProducerMultiOutput - returning with noop");
|
||||
return;
|
||||
}
|
||||
|
||||
metaDataProducerMultiOutputStack.pop();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user