diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerMultiOutput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerMultiOutput.java index d6797a2a..32c446a1 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerMultiOutput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerMultiOutput.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.metadata; import java.util.ArrayList; import java.util.List; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.SourceQBitAware; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; @@ -31,10 +32,12 @@ import com.kingsrook.qqq.backend.core.utils.CollectionUtils; ** Output object for a MetaDataProducer, which contains multiple meta-data ** objects. *******************************************************************************/ -public class MetaDataProducerMultiOutput implements MetaDataProducerOutput +public class MetaDataProducerMultiOutput implements MetaDataProducerOutput, SourceQBitAware { private List contents; + private String sourceQBitName; + /******************************************************************************* @@ -98,4 +101,48 @@ public class MetaDataProducerMultiOutput implements MetaDataProducerOutput return (rs); } + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public String getSourceQBitName() + { + return (this.sourceQBitName); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public void setSourceQBitName(String sourceQBitName) + { + this.sourceQBitName = sourceQBitName; + + ///////////////////////////////////////////// + // propagate the name down to the children // + ///////////////////////////////////////////// + for(MetaDataProducerOutput content : contents) + { + if(content instanceof SourceQBitAware aware) + { + aware.setSourceQBitName(sourceQBitName); + } + } + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public MetaDataProducerMultiOutput withSourceQBitName(String sourceQBitName) + { + setSourceQBitName(sourceQBitName); + return this; + } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java index a61971c8..def809b9 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java @@ -56,6 +56,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRule import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; 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.qbits.QBitMetaData; import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData; import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueProviderMetaData; import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData; @@ -89,6 +90,7 @@ public class QInstance //////////////////////////////////////////////////////////////////////////////////////////// // Important to use LinkedHashmap here, to preserve the order in which entries are added. // //////////////////////////////////////////////////////////////////////////////////////////// + private Map qBits = new LinkedHashMap<>(); private Map tables = new LinkedHashMap<>(); private Map joins = new LinkedHashMap<>(); private Map possibleValueSources = new LinkedHashMap<>(); @@ -1489,6 +1491,7 @@ public class QInstance } + /******************************************************************************* ** Getter for metaDataFilter *******************************************************************************/ @@ -1519,4 +1522,68 @@ public class QInstance } + + /******************************************************************************* + ** + *******************************************************************************/ + public void addQBit(QBitMetaData qBitMetaData) + { + List missingParts = new ArrayList<>(); + if(!StringUtils.hasContent(qBitMetaData.getGroupId())) + { + missingParts.add("groupId"); + } + if(!StringUtils.hasContent(qBitMetaData.getArtifactId())) + { + missingParts.add("artifactId"); + } + if(!StringUtils.hasContent(qBitMetaData.getVersion())) + { + missingParts.add("version"); + + } + if(!missingParts.isEmpty()) + { + throw (new IllegalArgumentException("Attempted to add a qBit without a " + StringUtils.joinWithCommasAndAnd(missingParts))); + } + + String name = qBitMetaData.getName(); + if(this.qBits.containsKey(name)) + { + throw (new IllegalArgumentException("Attempted to add a second qBit with name (formed from 'groupId:artifactId:version[:namespace]'): " + name)); + } + this.qBits.put(name, qBitMetaData); + } + + + + /******************************************************************************* + ** Getter for qBits + *******************************************************************************/ + public Map getQBits() + { + return (this.qBits); + } + + + + /******************************************************************************* + ** Setter for qBits + *******************************************************************************/ + public void setQBits(Map qBits) + { + this.qBits = qBits; + } + + + + /******************************************************************************* + ** Fluent setter for qBits + *******************************************************************************/ + public QInstance withQBits(Map qBits) + { + this.qBits = qBits; + return (this); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java index 582b36e2..21112267 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java @@ -37,6 +37,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData; import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon; import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules; import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.SourceQBitAware; import com.kingsrook.qqq.backend.core.model.metadata.scheduleing.QScheduleMetaData; import com.kingsrook.qqq.backend.core.processes.implementations.basepull.BasepullConfiguration; import com.kingsrook.qqq.backend.core.utils.StringUtils; @@ -46,11 +47,14 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils; ** Meta-Data to define a process in a QQQ instance. ** *******************************************************************************/ -public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissionRules, TopLevelMetaDataInterface +public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissionRules, TopLevelMetaDataInterface, SourceQBitAware { - private String name; - private String label; - private String tableName; + private String name; + private String label; + private String tableName; + + private String sourceQBitName; + private boolean isHidden = false; private BasepullConfiguration basepullConfiguration; private QPermissionRules permissionRules; @@ -870,6 +874,7 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi } + /******************************************************************************* ** Getter for processTracerCodeReference *******************************************************************************/ @@ -900,4 +905,37 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi } + /******************************************************************************* + ** Getter for sourceQBitName + *******************************************************************************/ + @Override + public String getSourceQBitName() + { + return (this.sourceQBitName); + } + + + + /******************************************************************************* + ** Setter for sourceQBitName + *******************************************************************************/ + @Override + public void setSourceQBitName(String sourceQBitName) + { + this.sourceQBitName = sourceQBitName; + } + + + + /******************************************************************************* + ** Fluent setter for sourceQBitName + *******************************************************************************/ + @Override + public QProcessMetaData withSourceQBitName(String sourceQBitName) + { + this.sourceQBitName = sourceQBitName; + return (this); + } + + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/ProvidedOrSuppliedTableConfig.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/ProvidedOrSuppliedTableConfig.java new file mode 100644 index 00000000..3383a4c6 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/ProvidedOrSuppliedTableConfig.java @@ -0,0 +1,122 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +/*************************************************************************** + ** Common (maybe)? qbit config pattern, where the qbit may be able to provide + ** a particular table, or, the application may supply it itself. + ** + ** If the qbit provides it, then we need to be told (by the application) + ** what backendName to use for the table. + ** + ** Else if the application supplies it, it needs to tell the qBit what the + ** tableName is. + ***************************************************************************/ +public class ProvidedOrSuppliedTableConfig +{ + private boolean doProvideTable; + private String backendName; + private String tableName; + + + + /*************************************************************************** + ** + ***************************************************************************/ + public ProvidedOrSuppliedTableConfig(boolean doProvideTable, String backendName, String tableName) + { + this.doProvideTable = doProvideTable; + this.backendName = backendName; + this.tableName = tableName; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static ProvidedOrSuppliedTableConfig provideTableUsingBackendNamed(String backendName) + { + return (new ProvidedOrSuppliedTableConfig(true, backendName, null)); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public static ProvidedOrSuppliedTableConfig useSuppliedTaleNamed(String tableName) + { + return (new ProvidedOrSuppliedTableConfig(false, null, tableName)); + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public String getEffectiveTableName(String tableNameIfProviding) + { + if (getDoProvideTable()) + { + return tableNameIfProviding; + } + else + { + return getTableName(); + } + } + + + + /******************************************************************************* + ** Getter for tableName + ** + *******************************************************************************/ + public String getTableName() + { + return tableName; + } + + + + /******************************************************************************* + ** Getter for doProvideTable + ** + *******************************************************************************/ + public boolean getDoProvideTable() + { + return doProvideTable; + } + + + + /******************************************************************************* + ** Getter for backendName + ** + *******************************************************************************/ + public String getBackendName() + { + return backendName; + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitComponentMetaDataProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitComponentMetaDataProducer.java new file mode 100644 index 00000000..346633f8 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitComponentMetaDataProducer.java @@ -0,0 +1,71 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerInterface; +import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerOutput; + + +/******************************************************************************* + ** extension of MetaDataProducerInterface, designed for producing meta data + ** within a (java-defined, at this time) QBit. + ** + ** Specifically exists to accept the QBitConfig as a type parameter and a value, + ** easily accessed in the producer's methods as getQBitConfig() + *******************************************************************************/ +public abstract class QBitComponentMetaDataProducer implements MetaDataProducerInterface +{ + private C qBitConfig = null; + + + + /******************************************************************************* + ** Getter for qBitConfig + *******************************************************************************/ + public C getQBitConfig() + { + return (this.qBitConfig); + } + + + + /******************************************************************************* + ** Setter for qBitConfig + *******************************************************************************/ + public void setQBitConfig(C qBitConfig) + { + this.qBitConfig = qBitConfig; + } + + + + /******************************************************************************* + ** Fluent setter for qBitConfig + *******************************************************************************/ + public QBitComponentMetaDataProducer withQBitConfig(C qBitConfig) + { + this.qBitConfig = qBitConfig; + return (this); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfig.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfig.java new file mode 100644 index 00000000..bb4ea5c1 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfig.java @@ -0,0 +1,110 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qqq.backend.core.logging.QLogger; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.producers.MetaDataCustomizerInterface; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** Interface for configuration settings used both in the production of meta-data + ** for a QBit, but also at runtime, e.g., to be aware of exactly how the qbit + ** has been incorporated into an application. + ** + ** For example: + ** - should the QBit define certain tables, or will they be supplied by the application? + ** - what other meta-data names should the qbit reference (backends, schedulers) + ** - what meta-data-customizer(s) should be used? + ** + ** When implementing a QBit, you'll implement this interface - adding whatever + ** (if any) properties you need, and if you have any rules, then overriding + ** the validate method (ideally the one that takes the List-of-String errors) + ** + ** When using a QBit, you'll create an instance of the QBit's config object, + ** and pass it through to the QBit producer. + *******************************************************************************/ +public interface QBitConfig extends Serializable +{ + QLogger LOG = QLogger.getLogger(QBitConfig.class); + + + /*************************************************************************** + ** + ***************************************************************************/ + default void validate(QInstance qInstance) throws QBitConfigValidationException + { + List errors = new ArrayList<>(); + + try + { + validate(qInstance, errors); + } + catch(Exception e) + { + LOG.warn("Error validating QBitConfig: " + this.getClass().getName(), e); + } + + if(!errors.isEmpty()) + { + throw (new QBitConfigValidationException(this, errors)); + } + } + + + /*************************************************************************** + ** + ***************************************************************************/ + default void validate(QInstance qInstance, List errors) + { + ///////////////////////////////////// + // nothing to validate by default! // + ///////////////////////////////////// + } + + + /*************************************************************************** + ** + ***************************************************************************/ + default boolean assertCondition(boolean condition, String message, List errors) + { + if(!condition) + { + errors.add(message); + } + return (condition); + } + + + /*************************************************************************** + ** + ***************************************************************************/ + default MetaDataCustomizerInterface getTableMetaDataCustomizer() + { + return (null); + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfigValidationException.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfigValidationException.java new file mode 100644 index 00000000..058442c5 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitConfigValidationException.java @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +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.utils.StringUtils; + + +/******************************************************************************* + ** thrown by QBitConfig.validate() if there's an issue. + *******************************************************************************/ +public class QBitConfigValidationException extends QException +{ + + /*************************************************************************** + ** + ***************************************************************************/ + public QBitConfigValidationException(QBitConfig qBitConfig, List errors) + { + super("Validation failed for QBitConfig: " + qBitConfig.getClass().getName() + ":\n" + StringUtils.join("\n", errors)); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitMetaData.java new file mode 100644 index 00000000..feacb969 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitMetaData.java @@ -0,0 +1,237 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.TopLevelMetaDataInterface; +import com.kingsrook.qqq.backend.core.utils.StringUtils; + + +/******************************************************************************* + ** Meta-data to define an active QBit in a QQQ Instance. + ** + ** The unique "name" for the QBit is composed of its groupId and artifactId + ** (maven style). There is also a version - but it is not part of the unique + ** name. But - there is also a namespace attribute, which IS part of the + ** unique name. This will (eventually?) allow us to have multiple instances + ** of the same qbit in a qInstance at the same time (e.g., 2 versions of some + ** table, which should be namespace-prefixed); + ** + ** QBitMetaData also retains the QBitConfig that was used to produce the QBit. + ** + ** Some meta-data objects are aware of the fact that they may have come from a + ** QBit - see SourceQBitAware interface. These objects can get their source + ** QBitMetaData (this object) and its config,via that interface. + *******************************************************************************/ +public class QBitMetaData implements TopLevelMetaDataInterface +{ + private String groupId; + private String artifactId; + private String version; + private String namespace; + + private QBitConfig config; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public String getName() + { + String name = groupId + ":" + artifactId; + if(StringUtils.hasContent(namespace)) + { + name += ":" + namespace; + } + return name; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public void addSelfToInstance(QInstance qInstance) + { + qInstance.addQBit(this); + } + + + + /******************************************************************************* + ** Getter for config + *******************************************************************************/ + public QBitConfig getConfig() + { + return (this.config); + } + + + + /******************************************************************************* + ** Setter for config + *******************************************************************************/ + public void setConfig(QBitConfig config) + { + this.config = config; + } + + + + /******************************************************************************* + ** Fluent setter for config + *******************************************************************************/ + public QBitMetaData withConfig(QBitConfig config) + { + this.config = config; + return (this); + } + + + + /******************************************************************************* + ** Getter for groupId + *******************************************************************************/ + public String getGroupId() + { + return (this.groupId); + } + + + + /******************************************************************************* + ** Setter for groupId + *******************************************************************************/ + public void setGroupId(String groupId) + { + this.groupId = groupId; + } + + + + /******************************************************************************* + ** Fluent setter for groupId + *******************************************************************************/ + public QBitMetaData withGroupId(String groupId) + { + this.groupId = groupId; + return (this); + } + + + + /******************************************************************************* + ** Getter for artifactId + *******************************************************************************/ + public String getArtifactId() + { + return (this.artifactId); + } + + + + /******************************************************************************* + ** Setter for artifactId + *******************************************************************************/ + public void setArtifactId(String artifactId) + { + this.artifactId = artifactId; + } + + + + /******************************************************************************* + ** Fluent setter for artifactId + *******************************************************************************/ + public QBitMetaData withArtifactId(String artifactId) + { + this.artifactId = artifactId; + return (this); + } + + + + /******************************************************************************* + ** Getter for version + *******************************************************************************/ + public String getVersion() + { + return (this.version); + } + + + + /******************************************************************************* + ** Setter for version + *******************************************************************************/ + public void setVersion(String version) + { + this.version = version; + } + + + + /******************************************************************************* + ** Fluent setter for version + *******************************************************************************/ + public QBitMetaData withVersion(String version) + { + this.version = version; + return (this); + } + + + + /******************************************************************************* + ** Getter for namespace + *******************************************************************************/ + public String getNamespace() + { + return (this.namespace); + } + + + + /******************************************************************************* + ** Setter for namespace + *******************************************************************************/ + public void setNamespace(String namespace) + { + this.namespace = namespace; + } + + + + /******************************************************************************* + ** Fluent setter for namespace + *******************************************************************************/ + public QBitMetaData withNamespace(String namespace) + { + this.namespace = namespace; + return (this); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducer.java new file mode 100644 index 00000000..7fef2174 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducer.java @@ -0,0 +1,117 @@ +/* + * 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 . + */ + +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.logging.QLogger; +import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerInterface; +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 static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; + + +/******************************************************************************* + ** interface for how a QBit's meta-data gets produced and added to a QInstance. + ** + ** When implementing a QBit, you'll implement this interface: + ** - adding a QBitConfig subclass as a property + ** - overriding the produce(qInstance, namespace) method - where you'll: + ** -- create and add your QBitMetaData + ** -- call MetaDataProducerHelper.findProducers + ** -- hand off to finishProducing() in this interface + ** + ** When using a QBit, you'll create an instance of the QBit's config object, + ** pass it in to the producer, then call produce, ala: + ** + ** new SomeQBitProducer() + ** .withQBitConfig(someQBitConfig) + ** .produce(qInstance); + ** + *******************************************************************************/ +public interface QBitProducer +{ + QLogger LOG = QLogger.getLogger(QBitProducer.class); + + + /*************************************************************************** + ** + ***************************************************************************/ + default void produce(QInstance qInstance) throws QException + { + produce(qInstance, null); + } + + /*************************************************************************** + ** + ***************************************************************************/ + void produce(QInstance qInstance, String namespace) throws QException; + + + /*************************************************************************** + * + ***************************************************************************/ + default void finishProducing(QInstance qInstance, QBitMetaData qBitMetaData, C qBitConfig, List> producers) throws QException + { + qBitConfig.validate(qInstance); + + /////////////////////////////// + // todo - move to base class // + /////////////////////////////// + for(MetaDataProducerInterface producer : producers) + { + if(producer instanceof QBitComponentMetaDataProducer) + { + QBitComponentMetaDataProducer qBitComponentMetaDataProducer = (QBitComponentMetaDataProducer) producer; + qBitComponentMetaDataProducer.setQBitConfig(qBitConfig); + } + + if(!producer.isEnabled()) + { + LOG.debug("Not using producer which is not enabled", logPair("producer", producer.getClass().getSimpleName())); + continue; + } + + MetaDataProducerOutput output = producer.produce(qInstance); + + ///////////////////////////////////////// + // apply table customizer, if provided // + ///////////////////////////////////////// + if(qBitConfig.getTableMetaDataCustomizer() != null && output instanceof QTableMetaData table) + { + output = qBitConfig.getTableMetaDataCustomizer().customizeMetaData(qInstance, table); + } + + ///////////////////////////////////////////////// + // set source qbit, if output is aware of such // + ///////////////////////////////////////////////// + if(output instanceof SourceQBitAware sourceQBitAware) + { + sourceQBitAware.setSourceQBitName(qBitMetaData.getName()); + } + + output.addSelfToInstance(qInstance); + } + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/SourceQBitAware.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/SourceQBitAware.java new file mode 100644 index 00000000..c4d4be7f --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/SourceQBitAware.java @@ -0,0 +1,77 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +import com.kingsrook.qqq.backend.core.context.QContext; + + +/******************************************************************************* + ** interface for meta data objects that may have come from a qbit, and where we + ** might want to get data about that qbit (e.g., config or meta-data). + *******************************************************************************/ +public interface SourceQBitAware +{ + /******************************************************************************* + ** Getter for sourceQBitName + *******************************************************************************/ + String getSourceQBitName(); + + + /******************************************************************************* + ** Setter for sourceQBitName + *******************************************************************************/ + void setSourceQBitName(String sourceQBitName); + + + /******************************************************************************* + ** Fluent setter for sourceQBitName + *******************************************************************************/ + Object withSourceQBitName(String sourceQBitName); + + + /*************************************************************************** + ** + ***************************************************************************/ + default QBitMetaData getSourceQBit() + { + String qbitName = getSourceQBitName(); + return (QContext.getQInstance().getQBits().get(qbitName)); + } + + + /*************************************************************************** + ** + ***************************************************************************/ + default QBitConfig getSourceQBitConfig() + { + QBitMetaData sourceQBit = getSourceQBit(); + if(sourceQBit == null) + { + return null; + } + else + { + return sourceQBit.getConfig(); + } + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QTableMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QTableMetaData.java index 0d0d6152..b2318de5 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QTableMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QTableMetaData.java @@ -50,6 +50,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData; import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon; import com.kingsrook.qqq.backend.core.model.metadata.permissions.MetaDataWithPermissionRules; import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.SourceQBitAware; import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock; import com.kingsrook.qqq.backend.core.model.metadata.sharing.ShareableTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.QTableAutomationDetails; @@ -62,7 +63,7 @@ import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; ** Meta-Data to define a table in a QQQ instance. ** *******************************************************************************/ -public class QTableMetaData implements QAppChildMetaData, Serializable, MetaDataWithPermissionRules, TopLevelMetaDataInterface +public class QTableMetaData implements QAppChildMetaData, Serializable, MetaDataWithPermissionRules, TopLevelMetaDataInterface, SourceQBitAware { private static final QLogger LOG = QLogger.getLogger(QTableMetaData.class); @@ -73,6 +74,8 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData private String primaryKeyField; private boolean isHidden = false; + private String sourceQBitName; + private Map fields; private List uniqueKeys; private List associations; @@ -1554,4 +1557,38 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData QInstanceHelpContentManager.removeHelpContentByRoleSetFromList(roles, listForSlot); } + + /******************************************************************************* + ** Getter for sourceQBitName + *******************************************************************************/ + @Override + public String getSourceQBitName() + { + return (this.sourceQBitName); + } + + + + /******************************************************************************* + ** Setter for sourceQBitName + *******************************************************************************/ + @Override + public void setSourceQBitName(String sourceQBitName) + { + this.sourceQBitName = sourceQBitName; + } + + + + /******************************************************************************* + ** Fluent setter for sourceQBitName + *******************************************************************************/ + @Override + public QTableMetaData withSourceQBitName(String sourceQBitName) + { + this.sourceQBitName = sourceQBitName; + return (this); + } + + } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducerTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducerTest.java new file mode 100644 index 00000000..de56fbfc --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/QBitProducerTest.java @@ -0,0 +1,151 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits; + + +import java.util.LinkedHashMap; +import com.kingsrook.qqq.backend.core.BaseTest; +import com.kingsrook.qqq.backend.core.context.QContext; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +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.qbits.testqbit.TestQBitConfig; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.TestQBitProducer; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.metadata.OtherTableMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.metadata.SomeTableMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; +import com.kingsrook.qqq.backend.core.utils.TestUtils; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + + +/******************************************************************************* + ** Unit test for QBitProducer + *******************************************************************************/ +class QBitProducerTest extends BaseTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() throws QException + { + TestQBitConfig config = new TestQBitConfig() + .withOtherTableConfig(ProvidedOrSuppliedTableConfig.provideTableUsingBackendNamed(TestUtils.MEMORY_BACKEND_NAME)) + .withIsSomeTableEnabled(true) + .withSomeSetting("yes") + .withTableMetaDataCustomizer((i, table) -> + { + if(table.getBackendName() == null) + { + table.setBackendName(TestUtils.DEFAULT_BACKEND_NAME); + } + + table.addField(new QFieldMetaData("custom", QFieldType.STRING)); + + return (table); + }); + + QInstance qInstance = QContext.getQInstance(); + new TestQBitProducer().withTestQBitConfig(config).produce(qInstance); + + /////////////////////////////////////////////////////////////////////////////////////////////////////// + // OtherTable should have been provided by the qbit, with the backend name we told it above (MEMORY) // + /////////////////////////////////////////////////////////////////////////////////////////////////////// + QTableMetaData otherTable = qInstance.getTable(OtherTableMetaDataProducer.NAME); + assertNotNull(otherTable); + assertEquals(TestUtils.MEMORY_BACKEND_NAME, otherTable.getBackendName()); + assertNotNull(otherTable.getField("custom")); + + QBitMetaData sourceQBit = otherTable.getSourceQBit(); + assertEquals("testQBit", sourceQBit.getArtifactId()); + + //////////////////////////////////////////////////////////////////////////////// + // SomeTable should have been provided, w/ backend name set by the customizer // + //////////////////////////////////////////////////////////////////////////////// + QTableMetaData someTable = qInstance.getTable(SomeTableMetaDataProducer.NAME); + assertNotNull(someTable); + assertEquals(TestUtils.DEFAULT_BACKEND_NAME, someTable.getBackendName()); + assertNotNull(otherTable.getField("custom")); + + TestQBitConfig qBitConfig = (TestQBitConfig) someTable.getSourceQBitConfig(); + assertEquals("yes", qBitConfig.getSomeSetting()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testDisableThings() throws QException + { + TestQBitConfig config = new TestQBitConfig() + .withOtherTableConfig(ProvidedOrSuppliedTableConfig.useSuppliedTaleNamed(TestUtils.TABLE_NAME_PERSON_MEMORY)) + .withIsSomeTableEnabled(false); + + QInstance qInstance = QContext.getQInstance(); + new TestQBitProducer().withTestQBitConfig(config).produce(qInstance); + + ////////////////////////////////////// + // neither table should be produced // + ////////////////////////////////////// + QTableMetaData otherTable = qInstance.getTable(OtherTableMetaDataProducer.NAME); + assertNull(otherTable); + + QTableMetaData someTable = qInstance.getTable(SomeTableMetaDataProducer.NAME); + assertNull(someTable); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testValidationErrors() throws QException + { + QInstance qInstance = QContext.getQInstance(); + TestQBitConfig config = new TestQBitConfig(); + + assertThatThrownBy(() -> new TestQBitProducer().withTestQBitConfig(config).produce(qInstance)) + .isInstanceOf(QBitConfigValidationException.class) + .hasMessageContaining("otherTableConfig must be set") + .hasMessageContaining("isSomeTableEnabled must be set"); + qInstance.setQBits(new LinkedHashMap<>()); + + config.setIsSomeTableEnabled(true); + assertThatThrownBy(() -> new TestQBitProducer().withTestQBitConfig(config).produce(qInstance)) + .isInstanceOf(QBitConfigValidationException.class) + .hasMessageContaining("otherTableConfig must be set"); + qInstance.setQBits(new LinkedHashMap<>()); + + config.setOtherTableConfig(ProvidedOrSuppliedTableConfig.useSuppliedTaleNamed(TestUtils.TABLE_NAME_PERSON_MEMORY)); + new TestQBitProducer().withTestQBitConfig(config).produce(qInstance); + } + +} \ No newline at end of file diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitConfig.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitConfig.java new file mode 100644 index 00000000..05ac39a9 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitConfig.java @@ -0,0 +1,181 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.producers.MetaDataCustomizerInterface; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.ProvidedOrSuppliedTableConfig; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.QBitConfig; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class TestQBitConfig implements QBitConfig +{ + private MetaDataCustomizerInterface tableMetaDataCustomizer; + + private Boolean isSomeTableEnabled; + private ProvidedOrSuppliedTableConfig otherTableConfig; + + private String someSetting; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public void validate(QInstance qInstance, List errors) + { + assertCondition(otherTableConfig != null, "otherTableConfig must be set", errors); + assertCondition(isSomeTableEnabled != null, "isSomeTableEnabled must be set", errors); + } + + + + /******************************************************************************* + ** Getter for otherTableConfig + *******************************************************************************/ + public ProvidedOrSuppliedTableConfig getOtherTableConfig() + { + return (this.otherTableConfig); + } + + + + /******************************************************************************* + ** Setter for otherTableConfig + *******************************************************************************/ + public void setOtherTableConfig(ProvidedOrSuppliedTableConfig otherTableConfig) + { + this.otherTableConfig = otherTableConfig; + } + + + + /******************************************************************************* + ** Fluent setter for otherTableConfig + *******************************************************************************/ + public TestQBitConfig withOtherTableConfig(ProvidedOrSuppliedTableConfig otherTableConfig) + { + this.otherTableConfig = otherTableConfig; + return (this); + } + + + + /******************************************************************************* + ** Getter for isSomeTableEnabled + *******************************************************************************/ + public Boolean getIsSomeTableEnabled() + { + return (this.isSomeTableEnabled); + } + + + + /******************************************************************************* + ** Setter for isSomeTableEnabled + *******************************************************************************/ + public void setIsSomeTableEnabled(Boolean isSomeTableEnabled) + { + this.isSomeTableEnabled = isSomeTableEnabled; + } + + + + /******************************************************************************* + ** Fluent setter for isSomeTableEnabled + *******************************************************************************/ + public TestQBitConfig withIsSomeTableEnabled(Boolean isSomeTableEnabled) + { + this.isSomeTableEnabled = isSomeTableEnabled; + return (this); + } + + + + /******************************************************************************* + ** Getter for tableMetaDataCustomizer + *******************************************************************************/ + public MetaDataCustomizerInterface getTableMetaDataCustomizer() + { + return (this.tableMetaDataCustomizer); + } + + + + /******************************************************************************* + ** Setter for tableMetaDataCustomizer + *******************************************************************************/ + public void setTableMetaDataCustomizer(MetaDataCustomizerInterface tableMetaDataCustomizer) + { + this.tableMetaDataCustomizer = tableMetaDataCustomizer; + } + + + + /******************************************************************************* + ** Fluent setter for tableMetaDataCustomizer + *******************************************************************************/ + public TestQBitConfig withTableMetaDataCustomizer(MetaDataCustomizerInterface tableMetaDataCustomizer) + { + this.tableMetaDataCustomizer = tableMetaDataCustomizer; + return (this); + } + + + + /******************************************************************************* + ** Getter for someSetting + *******************************************************************************/ + public String getSomeSetting() + { + return (this.someSetting); + } + + + + /******************************************************************************* + ** Setter for someSetting + *******************************************************************************/ + public void setSomeSetting(String someSetting) + { + this.someSetting = someSetting; + } + + + + /******************************************************************************* + ** Fluent setter for someSetting + *******************************************************************************/ + public TestQBitConfig withSomeSetting(String someSetting) + { + this.someSetting = someSetting; + return (this); + } + +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitProducer.java new file mode 100644 index 00000000..14c1d5d1 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/TestQBitProducer.java @@ -0,0 +1,92 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.exceptions.QException; +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.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.QBitMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.QBitProducer; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class TestQBitProducer implements QBitProducer +{ + private TestQBitConfig testQBitConfig; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public void produce(QInstance qInstance, String namespace) throws QException + { + QBitMetaData qBitMetaData = new QBitMetaData() + .withGroupId("test.com.kingsrook.qbits") + .withArtifactId("testQBit") + .withVersion("0.1.0") + .withNamespace(namespace) + .withConfig(testQBitConfig); + qInstance.addQBit(qBitMetaData); + + List> producers = MetaDataProducerHelper.findProducers(getClass().getPackageName() + ".metadata"); + finishProducing(qInstance, qBitMetaData, testQBitConfig, producers); + } + + + + /******************************************************************************* + ** Getter for testQBitConfig + *******************************************************************************/ + public TestQBitConfig getTestQBitConfig() + { + return (this.testQBitConfig); + } + + + + /******************************************************************************* + ** Setter for testQBitConfig + *******************************************************************************/ + public void setTestQBitConfig(TestQBitConfig testQBitConfig) + { + this.testQBitConfig = testQBitConfig; + } + + + + /******************************************************************************* + ** Fluent setter for testQBitConfig + *******************************************************************************/ + public TestQBitProducer withTestQBitConfig(TestQBitConfig testQBitConfig) + { + this.testQBitConfig = testQBitConfig; + return (this); + } + +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/OtherTableMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/OtherTableMetaDataProducer.java new file mode 100644 index 00000000..7660758c --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/OtherTableMetaDataProducer.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.metadata; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +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.qbits.QBitComponentMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.TestQBitConfig; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** Meta Data Producer for OtherTable + *******************************************************************************/ +public class OtherTableMetaDataProducer extends QBitComponentMetaDataProducer +{ + public static final String NAME = "otherTable"; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean isEnabled() + { + return (getQBitConfig().getOtherTableConfig().getDoProvideTable()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public QTableMetaData produce(QInstance qInstance) throws QException + { + QTableMetaData qTableMetaData = new QTableMetaData() + .withName(NAME) + .withPrimaryKeyField("id") + .withBackendName(getQBitConfig().getOtherTableConfig().getBackendName()) + .withField(new QFieldMetaData("id", QFieldType.INTEGER)); + + return (qTableMetaData); + } + +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/SomeTableMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/SomeTableMetaDataProducer.java new file mode 100644 index 00000000..3ef79554 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/qbits/testqbit/metadata/SomeTableMetaDataProducer.java @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.metadata; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +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.qbits.QBitComponentMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.qbits.testqbit.TestQBitConfig; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; + + +/******************************************************************************* + ** Meta Data Producer for SomeTable + *******************************************************************************/ +public class SomeTableMetaDataProducer extends QBitComponentMetaDataProducer +{ + public static final String NAME = "someTable"; + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public boolean isEnabled() + { + return (getQBitConfig().getIsSomeTableEnabled()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public QTableMetaData produce(QInstance qInstance) throws QException + { + QTableMetaData qTableMetaData = new QTableMetaData() + .withName(NAME) + .withPrimaryKeyField("id") + .withField(new QFieldMetaData("id", QFieldType.INTEGER)); + + return (qTableMetaData); + } + +}