diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidationState.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidationState.java
new file mode 100644
index 00000000..54bbde9c
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidationState.java
@@ -0,0 +1,34 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2022. Kingsrook, LLC
+ * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
+ * contact@kingsrook.com
+ * https://github.com/Kingsrook/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package com.kingsrook.qqq.backend.core.instances;
+
+
+/*******************************************************************************
+ ** Object used to record state of a QInstance having been validated.
+ **
+ *******************************************************************************/
+public enum QInstanceValidationState
+{
+ PENDING,
+ RUNNING,
+ COMPLETE
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
index 765e8e7c..9ece09aa 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java
@@ -139,14 +139,20 @@ public class QInstanceValidator
*******************************************************************************/
public void validate(QInstance qInstance) throws QInstanceValidationException
{
- if(qInstance.getHasBeenValidated())
+ if(qInstance.getHasBeenValidated() || qInstance.getValidationIsRunning())
{
- //////////////////////////////////////////
- // don't re-validate if previously done //
- //////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // don't re-validate if previously complete or currently running (avoids recursive re-validation chaos!) //
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
return;
}
+ ////////////////////////////////////
+ // mark validation as running now //
+ ////////////////////////////////////
+ QInstanceValidationKey validationKey = new QInstanceValidationKey();
+ qInstance.setValidationIsRunning(validationKey);
+
/////////////////////////////////////////////////////////////////////////////////////////////////////
// the enricher will build a join graph (if there are any joins). we'd like to only do that //
// once, during the enrichment/validation work, so, capture it, and store it back in the instance. //
@@ -207,9 +213,11 @@ public class QInstanceValidator
throw (new QInstanceValidationException(errors));
}
- QInstanceValidationKey validationKey = new QInstanceValidationKey();
- qInstance.setHasBeenValidated(validationKey);
+ //////////////////////////////
+ // mark validation complete //
+ //////////////////////////////
qInstance.setJoinGraph(validationKey, joinGraph);
+ qInstance.setHasBeenValidated(validationKey);
}
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 3efc1cda..fea69209 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
@@ -35,6 +35,7 @@ import com.kingsrook.qqq.backend.core.actions.metadata.MetaDataAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.instances.QInstanceHelpContentManager;
import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey;
+import com.kingsrook.qqq.backend.core.instances.QInstanceValidationState;
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
@@ -112,10 +113,13 @@ public class QInstance
private QPermissionRules defaultPermissionRules = QPermissionRules.defaultInstance();
private QAuditRules defaultAuditRules = QAuditRules.defaultInstanceLevelNone();
- // todo - lock down the object (no more changes allowed) after it's been validated?
+ //////////////////////////////////////////////////////////////////////////////////////
+ // todo - lock down the object (no more changes allowed) after it's been validated? //
+ // if doing so, may need to copy all of the collections into read-only versions... //
+ //////////////////////////////////////////////////////////////////////////////////////
@JsonIgnore
- private boolean hasBeenValidated = false;
+ private QInstanceValidationState validationState = QInstanceValidationState.PENDING;
private Map memoizedTablePaths = new HashMap<>();
private Map memoizedProcessPaths = new HashMap<>();
@@ -799,32 +803,58 @@ public class QInstance
*******************************************************************************/
public boolean getHasBeenValidated()
{
- return hasBeenValidated;
+ return validationState.equals(QInstanceValidationState.COMPLETE);
}
/*******************************************************************************
** If pass a QInstanceValidationKey (which can only be instantiated by the validator),
- ** then the hasBeenValidated field will be set to true.
+ ** then the validationState will be set to COMPLETE.
**
- ** Else, if passed a null, hasBeenValidated will be reset to false - e.g., to
+ ** Else, if passed a null, the validationState will be reset to PENDING. e.g., to
** re-trigger validation (can be useful in tests).
*******************************************************************************/
public void setHasBeenValidated(QInstanceValidationKey key)
{
if(key == null)
{
- this.hasBeenValidated = false;
+ this.validationState = QInstanceValidationState.PENDING;
}
else
{
- this.hasBeenValidated = true;
+ this.validationState = QInstanceValidationState.COMPLETE;
}
}
+ /*******************************************************************************
+ ** If pass a QInstanceValidationKey (which can only be instantiated by the validator),
+ ** then the validationState set to RUNNING.
+ **
+ *******************************************************************************/
+ public void setValidationIsRunning(QInstanceValidationKey key)
+ {
+ if(key != null)
+ {
+ this.validationState = QInstanceValidationState.RUNNING;
+ }
+ }
+
+
+
+ /*******************************************************************************
+ ** check if the instance is currently running validation.
+ **
+ *******************************************************************************/
+ public boolean getValidationIsRunning()
+ {
+ return validationState.equals(QInstanceValidationState.RUNNING);
+ }
+
+
+
/*******************************************************************************
** Getter for branding
**