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 **