001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.workflow.server.logic; 018 019import com.echothree.control.user.workflow.common.spec.WorkflowStepUniversalSpec; 020import com.echothree.model.control.core.common.ComponentVendors; 021import com.echothree.model.control.core.common.EntityTypes; 022import com.echothree.model.control.core.common.exception.InvalidParameterCountException; 023import com.echothree.model.control.core.server.control.EntityInstanceControl; 024import com.echothree.model.control.core.server.logic.EntityInstanceLogic; 025import com.echothree.model.control.workflow.common.exception.MissingRequiredWorkflowNameException; 026import com.echothree.model.control.workflow.common.exception.UnknownDefaultWorkflowStepException; 027import com.echothree.model.control.workflow.common.exception.UnknownWorkflowStepNameException; 028import com.echothree.model.control.workflow.server.control.WorkflowControl; 029import com.echothree.model.data.core.server.entity.EntityInstance; 030import com.echothree.model.data.workflow.server.entity.Workflow; 031import com.echothree.model.data.workflow.server.entity.WorkflowEntityStatus; 032import com.echothree.model.data.workflow.server.entity.WorkflowStep; 033import com.echothree.util.common.exception.BaseException; 034import com.echothree.util.common.message.ExecutionErrors; 035import com.echothree.util.common.persistence.BasePK; 036import com.echothree.util.server.control.BaseLogic; 037import com.echothree.util.server.message.ExecutionErrorAccumulator; 038import com.echothree.util.server.persistence.BaseEntity; 039import com.echothree.util.server.persistence.EntityPermission; 040import com.echothree.util.server.validation.ParameterUtils; 041import java.util.Arrays; 042import java.util.HashSet; 043import java.util.Set; 044import javax.enterprise.context.ApplicationScoped; 045import javax.inject.Inject; 046 047@ApplicationScoped 048public class WorkflowStepLogic 049 extends BaseLogic { 050 051 @Inject 052 EntityInstanceControl entityInstanceControl; 053 054 @Inject 055 WorkflowControl workflowControl; 056 057 @Inject 058 EntityInstanceLogic entityInstanceLogic; 059 060 @Inject 061 WorkflowLogic workflowLogic; 062 063 protected WorkflowStepLogic() { 064 super(); 065 } 066 067 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownWorkflowException, final ExecutionErrors unknownWorkflowExecutionError, 068 final Class<? extends BaseException> unknownWorkflowStepException, final ExecutionErrors unknownWorkflowStepExecutionError, 069 final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 070 var workflow = workflowLogic.getWorkflowByName(unknownWorkflowException, unknownWorkflowExecutionError, 071 eea, workflowName, EntityPermission.READ_ONLY); 072 WorkflowStep workflowStep = null; 073 074 if(eea == null || !eea.hasExecutionErrors()) { 075 workflowStep = getWorkflowStepByName(unknownWorkflowStepException, unknownWorkflowStepExecutionError, eea, 076 workflow, workflowStepName); 077 } 078 079 return workflowStep; 080 } 081 082 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 083 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName, EntityPermission entityPermission) { 084 var workflowStep = workflowControl.getWorkflowStepByName(workflow, workflowStepName, entityPermission); 085 086 if(workflowStep == null) { 087 handleExecutionError(unknownException, eea, unknownExecutionError.name(), workflow.getLastDetail().getWorkflowName(), 088 workflowStepName); 089 } 090 091 return workflowStep; 092 } 093 094 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 095 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 096 return getWorkflowStepByName(unknownException, unknownExecutionError, eea, workflow, workflowStepName, EntityPermission.READ_ONLY); 097 } 098 099 public WorkflowStep getWorkflowStepByNameForUpdate(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 100 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 101 return getWorkflowStepByName(unknownException, unknownExecutionError, eea, workflow, workflowStepName, EntityPermission.READ_WRITE); 102 } 103 104 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName, 105 final EntityPermission entityPermission) { 106 return getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 107 eea, workflow, workflowStepName, entityPermission); 108 } 109 110 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 111 return getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 112 eea, workflow, workflowStepName); 113 } 114 115 public WorkflowStep getWorkflowStepByNameForUpdate(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 116 return getWorkflowStepByNameForUpdate(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 117 eea, workflow, workflowStepName); 118 } 119 120 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName, 121 final EntityPermission entityPermission) { 122 var workflow = workflowLogic.getWorkflowByName(eea, workflowName); 123 WorkflowStep workflowStep = null; 124 125 if(eea == null || !eea.hasExecutionErrors()) { 126 workflowStep = getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 127 eea, workflow, workflowStepName, entityPermission); 128 } 129 130 return workflowStep; 131 } 132 133 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 134 return getWorkflowStepByName(eea, workflowName, workflowStepName, EntityPermission.READ_ONLY); 135 } 136 137 public WorkflowStep getWorkflowStepByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 138 return getWorkflowStepByName(eea, workflowName, workflowStepName, EntityPermission.READ_WRITE); 139 } 140 141 public WorkflowStep getWorkflowStepByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 142 final boolean allowDefault, final EntityPermission entityPermission) { 143 var workflowName = universalSpec.getWorkflowName(); 144 var workflowStepName = universalSpec.getWorkflowStepName(); 145 var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(workflowName, workflowStepName); 146 var possibleEntitySpecs= entityInstanceLogic.countPossibleEntitySpecs(universalSpec); 147 WorkflowStep workflowStep = null; 148 149 if(nameParameterCount < 3 && possibleEntitySpecs == 0) { 150 Workflow workflow = null; 151 152 if(workflowName != null) { 153 workflow = workflowLogic.getWorkflowByName(eea, workflowName); 154 } else { 155 handleExecutionError(MissingRequiredWorkflowNameException.class, eea, ExecutionErrors.MissingRequiredWorkflowName.name()); 156 } 157 158 if(eea == null || !eea.hasExecutionErrors()) { 159 if(workflowStepName == null) { 160 if(allowDefault) { 161 workflowStep = workflowControl.getDefaultWorkflowStep(workflow, entityPermission); 162 163 if(workflowStep == null) { 164 handleExecutionError(UnknownDefaultWorkflowStepException.class, eea, ExecutionErrors.UnknownDefaultWorkflowStep.name()); 165 } 166 } else { 167 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 168 } 169 } else { 170 workflowStep = getWorkflowStepByName(eea, workflow, workflowStepName, entityPermission); 171 } 172 } 173 } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) { 174 var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec, 175 ComponentVendors.ECHO_THREE.name(), EntityTypes.WorkflowStep.name()); 176 177 if(eea == null || !eea.hasExecutionErrors()) { 178 workflowStep = workflowControl.getWorkflowStepByEntityInstance(entityInstance, entityPermission); 179 } 180 } else { 181 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 182 } 183 184 return workflowStep; 185 } 186 187 public WorkflowStep getWorkflowStepByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 188 boolean allowDefault) { 189 return getWorkflowStepByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY); 190 } 191 192 public WorkflowStep getWorkflowStepByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 193 boolean allowDefault) { 194 return getWorkflowStepByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE); 195 } 196 197 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 198 String... workflowStepNames) { 199 return isEntityInWorkflowSteps(eea, workflowName, baseEntity, EntityPermission.READ_ONLY, workflowStepNames); 200 } 201 202 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 203 String... workflowStepNames) { 204 return isEntityInWorkflowSteps(eea, workflowName, baseEntity, EntityPermission.READ_WRITE, workflowStepNames); 205 } 206 207 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 208 EntityPermission entityPermission, String... workflowStepNames) { 209 return isEntityInWorkflowSteps(eea, workflowName, baseEntity.getPrimaryKey(), entityPermission, workflowStepNames); 210 } 211 212 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 213 String... workflowStepNames) { 214 return isEntityInWorkflowSteps(eea, workflowName, pk, EntityPermission.READ_ONLY, workflowStepNames); 215 } 216 217 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 218 String... workflowStepNames) { 219 return isEntityInWorkflowSteps(eea, workflowName, pk, EntityPermission.READ_WRITE, workflowStepNames); 220 } 221 222 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 223 EntityPermission entityPermission, String... workflowStepNames) { 224 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(pk); 225 226 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, entityPermission, workflowStepNames); 227 } 228 229 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 230 final String... workflowStepNames) { 231 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, EntityPermission.READ_ONLY, workflowStepNames); 232 } 233 234 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 235 final String... workflowStepNames) { 236 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, EntityPermission.READ_WRITE, workflowStepNames); 237 } 238 239 private Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 240 final EntityPermission entityPermission, final String... workflowStepNames) { 241 var workflow = workflowLogic.getWorkflowByName(eea, workflowName); 242 Set<WorkflowEntityStatus> result = new HashSet<>(); 243 244 if(!hasExecutionErrors(eea)) { 245 var workflowEntityStatuses = workflowControl.getWorkflowEntityStatusesByEntityInstance(workflow, entityInstance, entityPermission); 246 Set<String> possibleWorkflowStepNames = new HashSet<>(workflowStepNames.length); 247 248 possibleWorkflowStepNames.addAll(Arrays.asList(workflowStepNames)); 249 250 workflowEntityStatuses.forEach((workflowEntityStatus) -> { 251 var workflowStepDetail = workflowEntityStatus.getWorkflowStep().getLastDetail(); 252 if (workflowStepDetail.getWorkflow().equals(workflow)) { 253 var workflowStepName = workflowStepDetail.getWorkflowStepName(); 254 if (possibleWorkflowStepNames.contains(workflowStepName)) { 255 result.add(workflowEntityStatus); 256 } 257 } 258 }); 259 260 } 261 262 return result; 263 } 264 265 public boolean isWorkflowStepInSet(Set<WorkflowEntityStatus> workflowEntityStatuses, String workflowStepName) { 266 var result = false; 267 268 for(var workflowEntityStatus : workflowEntityStatuses) { 269 if(result |= workflowEntityStatus.getWorkflowStep().getLastDetail().getWorkflowStepName().equals(workflowStepName)) { 270 break; 271 } 272 } 273 274 return result; 275 } 276 277}