001// -------------------------------------------------------------------------------- 002// Copyright 2002-2025 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.persistence.Session; 041import com.echothree.util.server.validation.ParameterUtils; 042import java.util.Arrays; 043import java.util.HashSet; 044import java.util.Set; 045import javax.enterprise.context.ApplicationScoped; 046import javax.enterprise.inject.spi.CDI; 047 048@ApplicationScoped 049public class WorkflowStepLogic 050 extends BaseLogic { 051 052 protected WorkflowStepLogic() { 053 super(); 054 } 055 056 public static WorkflowStepLogic getInstance() { 057 return CDI.current().select(WorkflowStepLogic.class).get(); 058 } 059 060 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownWorkflowException, final ExecutionErrors unknownWorkflowExecutionError, 061 final Class<? extends BaseException> unknownWorkflowStepException, final ExecutionErrors unknownWorkflowStepExecutionError, 062 final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 063 var workflow = WorkflowLogic.getInstance().getWorkflowByName(unknownWorkflowException, unknownWorkflowExecutionError, 064 eea, workflowName, EntityPermission.READ_ONLY); 065 WorkflowStep workflowStep = null; 066 067 if(eea == null || !eea.hasExecutionErrors()) { 068 workflowStep = getWorkflowStepByName(unknownWorkflowStepException, unknownWorkflowStepExecutionError, eea, 069 workflow, workflowStepName); 070 } 071 072 return workflowStep; 073 } 074 075 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 076 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName, EntityPermission entityPermission) { 077 var workflowControl = Session.getModelController(WorkflowControl.class); 078 var workflowStep = workflowControl.getWorkflowStepByName(workflow, workflowStepName, entityPermission); 079 080 if(workflowStep == null) { 081 handleExecutionError(unknownException, eea, unknownExecutionError.name(), workflow.getLastDetail().getWorkflowName(), 082 workflowStepName); 083 } 084 085 return workflowStep; 086 } 087 088 public WorkflowStep getWorkflowStepByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 089 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 090 return getWorkflowStepByName(unknownException, unknownExecutionError, eea, workflow, workflowStepName, EntityPermission.READ_ONLY); 091 } 092 093 public WorkflowStep getWorkflowStepByNameForUpdate(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError, 094 final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 095 return getWorkflowStepByName(unknownException, unknownExecutionError, eea, workflow, workflowStepName, EntityPermission.READ_WRITE); 096 } 097 098 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName, 099 final EntityPermission entityPermission) { 100 return getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 101 eea, workflow, workflowStepName, entityPermission); 102 } 103 104 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 105 return getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 106 eea, workflow, workflowStepName); 107 } 108 109 public WorkflowStep getWorkflowStepByNameForUpdate(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowStepName) { 110 return getWorkflowStepByNameForUpdate(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 111 eea, workflow, workflowStepName); 112 } 113 114 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName, 115 final EntityPermission entityPermission) { 116 var workflow = WorkflowLogic.getInstance().getWorkflowByName(eea, workflowName); 117 WorkflowStep workflowStep = null; 118 119 if(eea == null || !eea.hasExecutionErrors()) { 120 workflowStep = getWorkflowStepByName(UnknownWorkflowStepNameException.class, ExecutionErrors.UnknownWorkflowStepName, 121 eea, workflow, workflowStepName, entityPermission); 122 } 123 124 return workflowStep; 125 } 126 127 public WorkflowStep getWorkflowStepByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 128 return getWorkflowStepByName(eea, workflowName, workflowStepName, EntityPermission.READ_ONLY); 129 } 130 131 public WorkflowStep getWorkflowStepByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowStepName) { 132 return getWorkflowStepByName(eea, workflowName, workflowStepName, EntityPermission.READ_WRITE); 133 } 134 135 public WorkflowStep getWorkflowStepByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 136 final boolean allowDefault, final EntityPermission entityPermission) { 137 var workflowControl = Session.getModelController(WorkflowControl.class); 138 var workflowName = universalSpec.getWorkflowName(); 139 var workflowStepName = universalSpec.getWorkflowStepName(); 140 var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(workflowName, workflowStepName); 141 var possibleEntitySpecs= EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalSpec); 142 WorkflowStep workflowStep = null; 143 144 if(nameParameterCount < 3 && possibleEntitySpecs == 0) { 145 Workflow workflow = null; 146 147 if(workflowName != null) { 148 workflow = WorkflowLogic.getInstance().getWorkflowByName(eea, workflowName); 149 } else { 150 handleExecutionError(MissingRequiredWorkflowNameException.class, eea, ExecutionErrors.MissingRequiredWorkflowName.name()); 151 } 152 153 if(!eea.hasExecutionErrors()) { 154 if(workflowStepName == null) { 155 if(allowDefault) { 156 workflowStep = workflowControl.getDefaultWorkflowStep(workflow, entityPermission); 157 158 if(workflowStep == null) { 159 handleExecutionError(UnknownDefaultWorkflowStepException.class, eea, ExecutionErrors.UnknownDefaultWorkflowStep.name()); 160 } 161 } else { 162 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 163 } 164 } else { 165 workflowStep = getWorkflowStepByName(eea, workflow, workflowStepName, entityPermission); 166 } 167 } 168 } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) { 169 var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalSpec, 170 ComponentVendors.ECHO_THREE.name(), EntityTypes.WorkflowStep.name()); 171 172 if(!eea.hasExecutionErrors()) { 173 workflowStep = workflowControl.getWorkflowStepByEntityInstance(entityInstance, entityPermission); 174 } 175 } else { 176 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 177 } 178 179 return workflowStep; 180 } 181 182 public WorkflowStep getWorkflowStepByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 183 boolean allowDefault) { 184 return getWorkflowStepByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY); 185 } 186 187 public WorkflowStep getWorkflowStepByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final WorkflowStepUniversalSpec universalSpec, 188 boolean allowDefault) { 189 return getWorkflowStepByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE); 190 } 191 192 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 193 String... workflowStepNames) { 194 return isEntityInWorkflowSteps(eea, workflowName, baseEntity, EntityPermission.READ_ONLY, workflowStepNames); 195 } 196 197 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 198 String... workflowStepNames) { 199 return isEntityInWorkflowSteps(eea, workflowName, baseEntity, EntityPermission.READ_WRITE, workflowStepNames); 200 } 201 202 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BaseEntity baseEntity, 203 EntityPermission entityPermission, String... workflowStepNames) { 204 return isEntityInWorkflowSteps(eea, workflowName, baseEntity.getPrimaryKey(), entityPermission, workflowStepNames); 205 } 206 207 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 208 String... workflowStepNames) { 209 return isEntityInWorkflowSteps(eea, workflowName, pk, EntityPermission.READ_ONLY, workflowStepNames); 210 } 211 212 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 213 String... workflowStepNames) { 214 return isEntityInWorkflowSteps(eea, workflowName, pk, EntityPermission.READ_WRITE, workflowStepNames); 215 } 216 217 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final BasePK pk, 218 EntityPermission entityPermission, String... workflowStepNames) { 219 var entityInstanceControl = Session.getModelController(EntityInstanceControl.class); 220 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(pk); 221 222 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, entityPermission, workflowStepNames); 223 } 224 225 public Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 226 final String... workflowStepNames) { 227 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, EntityPermission.READ_ONLY, workflowStepNames); 228 } 229 230 public Set<WorkflowEntityStatus> isEntityInWorkflowStepsForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 231 final String... workflowStepNames) { 232 return isEntityInWorkflowSteps(eea, workflowName, entityInstance, EntityPermission.READ_WRITE, workflowStepNames); 233 } 234 235 private Set<WorkflowEntityStatus> isEntityInWorkflowSteps(final ExecutionErrorAccumulator eea, final String workflowName, final EntityInstance entityInstance, 236 final EntityPermission entityPermission, final String... workflowStepNames) { 237 var workflow = WorkflowLogic.getInstance().getWorkflowByName(eea, workflowName); 238 Set<WorkflowEntityStatus> result = new HashSet<>(); 239 240 if(!hasExecutionErrors(eea)) { 241 var workflowControl = Session.getModelController(WorkflowControl.class); 242 var workflowEntityStatuses = workflowControl.getWorkflowEntityStatusesByEntityInstance(workflow, entityInstance, entityPermission); 243 Set<String> possibleWorkflowStepNames = new HashSet<>(workflowStepNames.length); 244 245 possibleWorkflowStepNames.addAll(Arrays.asList(workflowStepNames)); 246 247 workflowEntityStatuses.forEach((workflowEntityStatus) -> { 248 var workflowStepDetail = workflowEntityStatus.getWorkflowStep().getLastDetail(); 249 if (workflowStepDetail.getWorkflow().equals(workflow)) { 250 var workflowStepName = workflowStepDetail.getWorkflowStepName(); 251 if (possibleWorkflowStepNames.contains(workflowStepName)) { 252 result.add(workflowEntityStatus); 253 } 254 } 255 }); 256 257 } 258 259 return result; 260 } 261 262 public boolean isWorkflowStepInSet(Set<WorkflowEntityStatus> workflowEntityStatuses, String workflowStepName) { 263 var result = false; 264 265 for(var workflowEntityStatus : workflowEntityStatuses) { 266 if(result |= workflowEntityStatus.getWorkflowStep().getLastDetail().getWorkflowStepName().equals(workflowStepName)) { 267 break; 268 } 269 } 270 271 return result; 272 } 273 274}