diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/MetaDataProducerInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/MetaDataProducerInterface.java
new file mode 100644
index 00000000..45bd2ca6
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/MetaDataProducerInterface.java
@@ -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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model;
+
+
+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.TopLevelMetaDataInterface;
+
+
+/*******************************************************************************
+ ** Interface for classes that know how to produce meta data objects. Useful with
+ ** MetaDataProducerHelper, to put point at a package full of these, and populate
+ ** your whole QInstance.
+ **
+ ** See also MetaDataProducer - an implementer of this interface, which actually
+ ** came first, and is fine to extend if producing a meta-data class is all your
+ ** clas means to do (nice and "Single-responsibility principle").
+ **
+ ** But, in some applications you may want to, for example, have one class that
+ ** defines a process step, and also produces the meta-data for that process, so
+ ** your whole process can just be one class - so then just have your step class
+ ** implement this interface. or, same idea for a QRecordEntity that provides
+ ** its own TableMetaData.
+ *******************************************************************************/
+public interface MetaDataProducerInterface
+{
+ int DEFAULT_SORT_ORDER = 500;
+
+
+ /*******************************************************************************
+ ** Produce the metaData object. Generally, you don't want to add it to the instance
+ ** yourself - but the instance is there in case you need it to get other metaData.
+ *******************************************************************************/
+ T produce(QInstance qInstance) throws QException;
+
+
+ /*******************************************************************************
+ ** In case this producer needs to run before (or after) others, this method
+ ** can control influence that (e.g., if used by MetaDataProducerHelper).
+ **
+ ** Smaller values run first.
+ *******************************************************************************/
+ default int getSortOrder()
+ {
+ return (DEFAULT_SORT_ORDER);
+ }
+
+
+ /*******************************************************************************
+ ** turn this producer on or off - e.g., maybe based on an env value.
+ **
+ *******************************************************************************/
+ default boolean isEnabled()
+ {
+ return (true);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducer.java
index 1b3e2148..4207a132 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducer.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducer.java
@@ -22,7 +22,7 @@
package com.kingsrook.qqq.backend.core.model.metadata;
-import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
/*******************************************************************************
@@ -30,29 +30,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
** MetaDataProducerHelper, to put point at a package full of these, and populate
** your whole QInstance.
*******************************************************************************/
-public abstract class MetaDataProducer
+public abstract class MetaDataProducer implements MetaDataProducerInterface
{
- public static final int DEFAULT_SORT_ORDER = 500;
-
-
-
- /*******************************************************************************
- ** Produce the metaData object. Generally, you don't want to add it to the instance
- ** yourself - but the instance is there in case you need it to get other metaData.
- *******************************************************************************/
- public abstract T produce(QInstance qInstance) throws QException;
-
-
-
- /*******************************************************************************
- ** In case this producer needs to run before (or after) others, this method
- ** can control influence that (e.g., if used by MetaDataProducerHelper).
- **
- ** Smaller values run first.
- *******************************************************************************/
- public int getSortOrder()
- {
- return (DEFAULT_SORT_ORDER);
- }
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
index 7769c329..7a52a890 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java
@@ -30,6 +30,7 @@ import java.util.Comparator;
import java.util.List;
import com.google.common.reflect.ClassPath;
import com.kingsrook.qqq.backend.core.logging.QLogger;
+import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
@@ -44,7 +45,7 @@ public class MetaDataProducerHelper
/*******************************************************************************
- ** Recursively find all classes in the given package, that extend MetaDataProducer,
+ ** Recursively find all classes in the given package, that implement MetaDataProducerInterface
** run them, and add their output to the given qInstance.
**
** Note - they'll be sorted by the sortOrder they provide.
@@ -54,8 +55,8 @@ public class MetaDataProducerHelper
////////////////////////////////////////////////////////////////////////
// find all the meta data producer classes in (and under) the package //
////////////////////////////////////////////////////////////////////////
- List> classesInPackage = getClassesInPackage(packageName);
- List> producers = new ArrayList<>();
+ List> classesInPackage = getClassesInPackage(packageName);
+ List> producers = new ArrayList<>();
for(Class> aClass : classesInPackage)
{
try
@@ -65,22 +66,29 @@ public class MetaDataProducerHelper
continue;
}
- for(Constructor> constructor : aClass.getConstructors())
+ if(MetaDataProducerInterface.class.isAssignableFrom(aClass))
{
- if(constructor.getParameterCount() == 0)
+ boolean foundValidConstructor = false;
+ for(Constructor> constructor : aClass.getConstructors())
{
- Object o = constructor.newInstance();
- if(o instanceof MetaDataProducer> metaDataProducer)
+ if(constructor.getParameterCount() == 0)
{
- producers.add(metaDataProducer);
+ Object o = constructor.newInstance();
+ producers.add((MetaDataProducerInterface>) o);
+ foundValidConstructor = true;
+ break;
}
- break;
+ }
+
+ if(!foundValidConstructor)
+ {
+ LOG.warn("Found a class which implements MetaDataProducerInterface, but it does not have a no-arg constructor, so it cannot be used.", logPair("class", aClass.getSimpleName()));
}
}
}
catch(Exception e)
{
- LOG.info("Error adding metaData from producer", e, logPair("producer", aClass.getSimpleName()));
+ LOG.warn("Error evaluating a possible meta-data producer class", e, logPair("class", aClass.getSimpleName()));
}
}
@@ -89,8 +97,8 @@ public class MetaDataProducerHelper
// after all other types (as apps often try to get other types from the instance) //
////////////////////////////////////////////////////////////////////////////////////////////
producers.sort(Comparator
- .comparing((MetaDataProducer> p) -> p.getSortOrder())
- .thenComparing((MetaDataProducer> p) ->
+ .comparing((MetaDataProducerInterface> p) -> p.getSortOrder())
+ .thenComparing((MetaDataProducerInterface> p) ->
{
try
{
@@ -110,22 +118,29 @@ public class MetaDataProducerHelper
}
}));
- //////////////////////////////////////////////////////////////
- // execute each one, adding their meta data to the instance //
- //////////////////////////////////////////////////////////////
- for(MetaDataProducer> producer : producers)
+ ///////////////////////////////////////////////////////////////////////////
+ // execute each one (if enabled), adding their meta data to the instance //
+ ///////////////////////////////////////////////////////////////////////////
+ for(MetaDataProducerInterface> producer : producers)
{
- try
+ if(producer.isEnabled())
{
- TopLevelMetaDataInterface metaData = producer.produce(instance);
- if(metaData != null)
+ try
{
- metaData.addSelfToInstance(instance);
+ TopLevelMetaDataInterface metaData = producer.produce(instance);
+ if(metaData != null)
+ {
+ metaData.addSelfToInstance(instance);
+ }
+ }
+ catch(Exception e)
+ {
+ LOG.warn("error executing metaDataProducer", logPair("producer", producer.getClass().getSimpleName()), e);
}
}
- catch(Exception e)
+ else
{
- LOG.warn("error executing metaDataProducer", logPair("producer", producer.getClass().getSimpleName()), e);
+ LOG.debug("Not using producer which is not enabled", logPair("producer", producer.getClass().getSimpleName()));
}
}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
index 8c96b8ab..ab1ae66f 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java
@@ -23,8 +23,14 @@ package com.kingsrook.qqq.backend.core.model.metadata;
import java.io.IOException;
+import com.kingsrook.qqq.backend.core.model.metadata.producers.TestAbstractMetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.producers.TestDisabledMetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.producers.TestImplementsMetaDataProducer;
import com.kingsrook.qqq.backend.core.model.metadata.producers.TestMetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.producers.TestNoInterfacesExtendsObject;
+import com.kingsrook.qqq.backend.core.model.metadata.producers.TestNoValidConstructorMetaDataProducer;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -43,6 +49,11 @@ class MetaDataProducerHelperTest
QInstance qInstance = new QInstance();
MetaDataProducerHelper.processAllMetaDataProducersInPackage(qInstance, "com.kingsrook.qqq.backend.core.model.metadata.producers");
assertTrue(qInstance.getTables().containsKey(TestMetaDataProducer.NAME));
+ assertTrue(qInstance.getTables().containsKey(TestImplementsMetaDataProducer.NAME));
+ assertFalse(qInstance.getTables().containsKey(TestNoValidConstructorMetaDataProducer.NAME));
+ assertFalse(qInstance.getTables().containsKey(TestNoInterfacesExtendsObject.NAME));
+ assertFalse(qInstance.getTables().containsKey(TestAbstractMetaDataProducer.NAME));
+ assertFalse(qInstance.getTables().containsKey(TestDisabledMetaDataProducer.NAME));
}
}
\ No newline at end of file
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestAbstractMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestAbstractMetaDataProducer.java
new file mode 100644
index 00000000..041c1473
--- /dev/null
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestAbstractMetaDataProducer.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.metadata.producers;
+
+
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public abstract class TestAbstractMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "TestAbstractMetaDataProducer";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QTableMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QTableMetaData().withName(NAME);
+ }
+}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestDisabledMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestDisabledMetaDataProducer.java
new file mode 100644
index 00000000..5d2c3be7
--- /dev/null
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestDisabledMetaDataProducer.java
@@ -0,0 +1,59 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.metadata.producers;
+
+
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TestDisabledMetaDataProducer implements MetaDataProducerInterface
+{
+ public static final String NAME = "Disabled";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public boolean isEnabled()
+ {
+ return (false);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QTableMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QTableMetaData().withName(NAME);
+ }
+}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestImplementsMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestImplementsMetaDataProducer.java
new file mode 100644
index 00000000..14ce9359
--- /dev/null
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestImplementsMetaDataProducer.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.metadata.producers;
+
+
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TestImplementsMetaDataProducer implements MetaDataProducerInterface
+{
+ public static final String NAME = "BuiltByProducerImplementingInterface";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QTableMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QTableMetaData().withName(NAME);
+ }
+}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoInterfacesExtendsObject.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoInterfacesExtendsObject.java
new file mode 100644
index 00000000..e7cc6a0f
--- /dev/null
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoInterfacesExtendsObject.java
@@ -0,0 +1,46 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.metadata.producers;
+
+
+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.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TestNoInterfacesExtendsObject
+{
+ public static final String NAME = "TestNoInterfacesExtendsObject";
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QTableMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QTableMetaData().withName(NAME);
+ }
+}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoValidConstructorMetaDataProducer.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoValidConstructorMetaDataProducer.java
new file mode 100644
index 00000000..94463a54
--- /dev/null
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestNoValidConstructorMetaDataProducer.java
@@ -0,0 +1,58 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.metadata.producers;
+
+
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducer;
+import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class TestNoValidConstructorMetaDataProducer extends MetaDataProducer
+{
+ public static final String NAME = "NoValidConstructor";
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public TestNoValidConstructorMetaDataProducer(boolean b)
+ {
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public QTableMetaData produce(QInstance qInstance) throws QException
+ {
+ return new QTableMetaData().withName(NAME);
+ }
+}