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.WorkflowEntranceUniversalSpec;
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.logic.EntityInstanceLogic;
024import com.echothree.model.control.party.server.logic.PartyLogic;
025import com.echothree.model.control.security.server.logic.SecurityRoleLogic;
026import com.echothree.model.control.selector.server.logic.SelectorLogic;
027import com.echothree.model.control.workflow.common.exception.MissingRequiredWorkflowNameException;
028import com.echothree.model.control.workflow.common.exception.UnknownDefaultWorkflowEntranceException;
029import com.echothree.model.control.workflow.common.exception.UnknownEntranceWorkflowNameException;
030import com.echothree.model.control.workflow.common.exception.UnknownEntranceWorkflowStepNameException;
031import com.echothree.model.control.workflow.common.exception.UnknownWorkflowEntranceNameException;
032import com.echothree.model.control.workflow.common.exception.UnknownWorkflowEntrancePartyTypeException;
033import com.echothree.model.control.workflow.common.exception.UnknownWorkflowEntranceSecurityRoleException;
034import com.echothree.model.control.workflow.common.exception.UnknownWorkflowEntranceSelectorException;
035import com.echothree.model.control.workflow.common.exception.UnknownWorkflowEntranceStepException;
036import com.echothree.model.control.workflow.common.exception.WorkflowMissingSecurityRoleGroupException;
037import com.echothree.model.control.workflow.common.exception.WorkflowMissingSelectorTypeException;
038import com.echothree.model.control.workflow.server.control.WorkflowControl;
039import com.echothree.model.data.party.server.entity.PartyType;
040import com.echothree.model.data.workflow.server.entity.Workflow;
041import com.echothree.model.data.workflow.server.entity.WorkflowEntrance;
042import com.echothree.model.data.workflow.server.entity.WorkflowEntrancePartyType;
043import com.echothree.model.data.workflow.server.entity.WorkflowEntranceSecurityRole;
044import com.echothree.model.data.workflow.server.entity.WorkflowEntranceSelector;
045import com.echothree.model.data.workflow.server.entity.WorkflowEntranceStep;
046import com.echothree.model.data.workflow.server.entity.WorkflowStep;
047import com.echothree.util.common.exception.BaseException;
048import com.echothree.util.common.message.ExecutionErrors;
049import com.echothree.util.server.control.BaseLogic;
050import com.echothree.util.server.message.ExecutionErrorAccumulator;
051import com.echothree.util.server.persistence.EntityPermission;
052import com.echothree.util.server.validation.ParameterUtils;
053import javax.enterprise.context.ApplicationScoped;
054import javax.enterprise.inject.spi.CDI;
055import javax.inject.Inject;
056
057@ApplicationScoped
058public class WorkflowEntranceLogic
059        extends BaseLogic {
060
061    @Inject
062    WorkflowControl workflowControl;
063
064    @Inject
065    EntityInstanceLogic entityInstanceLogic;
066
067    @Inject
068    PartyLogic partyLogic;
069
070    @Inject
071    SecurityRoleLogic securityRoleLogic;
072
073    @Inject
074    SelectorLogic selectorLogic;
075
076    @Inject
077    WorkflowLogic workflowLogic;
078
079    @Inject
080    WorkflowStepLogic workflowStepLogic;
081
082    protected WorkflowEntranceLogic() {
083        super();
084    }
085
086    public static WorkflowEntranceLogic getInstance() {
087        return CDI.current().select(WorkflowEntranceLogic.class).get();
088    }
089
090    public WorkflowEntrance getWorkflowEntranceByName(final Class<? extends BaseException> unknownWorkflowException, final ExecutionErrors unknownWorkflowExecutionError,
091            final Class<? extends BaseException>  unknownWorkflowEntranceException, final ExecutionErrors unknownWorkflowEntranceExecutionError,
092            final ExecutionErrorAccumulator eea, final String workflowName, final String workflowEntranceName) {
093        var workflow = workflowLogic.getWorkflowByName(unknownWorkflowException, unknownWorkflowExecutionError,
094                eea, workflowName, EntityPermission.READ_ONLY);
095        WorkflowEntrance workflowEntrance = null;
096
097        if(eea == null || !eea.hasExecutionErrors()) {
098            workflowEntrance = getWorkflowEntranceByName(unknownWorkflowEntranceException, unknownWorkflowEntranceExecutionError, eea,
099                    workflow, workflowEntranceName);
100        }
101
102        return workflowEntrance;
103    }
104
105    public WorkflowEntrance getWorkflowEntranceByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
106            final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName, EntityPermission entityPermission) {
107        var workflowEntrance = workflowControl.getWorkflowEntranceByName(workflow, workflowEntranceName, entityPermission);
108
109        if(workflowEntrance == null) {
110            handleExecutionError(unknownException, eea, unknownExecutionError.name(), workflow.getLastDetail().getWorkflowName(),
111                    workflowEntranceName);
112        }
113
114        return workflowEntrance;
115    }
116
117    public WorkflowEntrance getWorkflowEntranceByName(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
118            final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName) {
119        return getWorkflowEntranceByName(unknownException, unknownExecutionError, eea, workflow, workflowEntranceName, EntityPermission.READ_ONLY);
120    }
121
122    public WorkflowEntrance getWorkflowEntranceByNameForUpdate(final Class<? extends BaseException> unknownException, final ExecutionErrors unknownExecutionError,
123            final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName) {
124        return getWorkflowEntranceByName(unknownException, unknownExecutionError, eea, workflow, workflowEntranceName, EntityPermission.READ_WRITE);
125    }
126
127    public WorkflowEntrance getWorkflowEntranceByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName,
128            final EntityPermission entityPermission) {
129        return getWorkflowEntranceByName(UnknownWorkflowEntranceNameException.class, ExecutionErrors.UnknownWorkflowEntranceName,
130                eea, workflow, workflowEntranceName, entityPermission);
131    }
132
133    public WorkflowEntrance getWorkflowEntranceByName(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName) {
134        return getWorkflowEntranceByName(UnknownWorkflowEntranceNameException.class, ExecutionErrors.UnknownWorkflowEntranceName,
135                eea, workflow, workflowEntranceName);
136    }
137
138    public WorkflowEntrance getWorkflowEntranceByNameForUpdate(final ExecutionErrorAccumulator eea, final Workflow workflow, final String workflowEntranceName) {
139        return getWorkflowEntranceByNameForUpdate(UnknownWorkflowEntranceNameException.class, ExecutionErrors.UnknownWorkflowEntranceName,
140                eea, workflow, workflowEntranceName);
141    }
142
143    public WorkflowEntrance getWorkflowEntranceByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowEntranceName,
144            final EntityPermission entityPermission) {
145        var workflow = workflowLogic.getWorkflowByName(eea, workflowName);
146        WorkflowEntrance workflowEntrance = null;
147
148        if(eea == null || !eea.hasExecutionErrors()) {
149            workflowEntrance = getWorkflowEntranceByName(UnknownWorkflowEntranceNameException.class, ExecutionErrors.UnknownWorkflowEntranceName,
150                    eea, workflow, workflowEntranceName, entityPermission);
151        }
152
153        return workflowEntrance;
154    }
155
156    public WorkflowEntrance getWorkflowEntranceByName(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowEntranceName) {
157        return getWorkflowEntranceByName(eea, workflowName, workflowEntranceName, EntityPermission.READ_ONLY);
158    }
159
160    public WorkflowEntrance getWorkflowEntranceByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName, final String workflowEntranceName) {
161        return getWorkflowEntranceByName(eea, workflowName, workflowEntranceName, EntityPermission.READ_WRITE);
162    }
163
164    public WorkflowEntrance getWorkflowEntranceByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowEntranceUniversalSpec universalSpec,
165            final boolean allowDefault, final EntityPermission entityPermission) {
166        var workflowName = universalSpec.getWorkflowName();
167        var workflowEntranceName = universalSpec.getWorkflowEntranceName();
168        var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(workflowName, workflowEntranceName);
169        var possibleEntitySpecs= entityInstanceLogic.countPossibleEntitySpecs(universalSpec);
170        WorkflowEntrance workflowEntrance = null;
171
172        if(nameParameterCount < 3 && possibleEntitySpecs == 0) {
173            Workflow workflow = null;
174
175            if(workflowName != null) {
176                workflow = workflowLogic.getWorkflowByName(eea, workflowName);
177            } else {
178                handleExecutionError(MissingRequiredWorkflowNameException.class, eea, ExecutionErrors.MissingRequiredWorkflowName.name());
179            }
180
181            if(eea == null || !eea.hasExecutionErrors()) {
182                if(workflowEntranceName == null) {
183                    if(allowDefault) {
184                        workflowEntrance = workflowControl.getDefaultWorkflowEntrance(workflow, entityPermission);
185
186                        if(workflowEntrance == null) {
187                            handleExecutionError(UnknownDefaultWorkflowEntranceException.class, eea, ExecutionErrors.UnknownDefaultWorkflowEntrance.name());
188                        }
189                    } else {
190                        handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
191                    }
192                } else {
193                    workflowEntrance = getWorkflowEntranceByName(eea, workflow, workflowEntranceName, entityPermission);
194                }
195            }
196        } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) {
197            var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec,
198                    ComponentVendors.ECHO_THREE.name(), EntityTypes.WorkflowEntrance.name());
199
200            if(eea == null || !eea.hasExecutionErrors()) {
201                workflowEntrance = workflowControl.getWorkflowEntranceByEntityInstance(entityInstance, entityPermission);
202            }
203        } else {
204            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
205        }
206
207        return workflowEntrance;
208    }
209
210    public WorkflowEntrance getWorkflowEntranceByUniversalSpec(final ExecutionErrorAccumulator eea, final WorkflowEntranceUniversalSpec universalSpec,
211            boolean allowDefault) {
212        return getWorkflowEntranceByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
213    }
214
215    public WorkflowEntrance getWorkflowEntranceByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final WorkflowEntranceUniversalSpec universalSpec,
216            boolean allowDefault) {
217        return getWorkflowEntranceByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
218    }
219
220    public WorkflowEntrancePartyType getWorkflowEntrancePartyType(final ExecutionErrorAccumulator eea, final WorkflowEntrance workflowEntrance,
221            final PartyType partyType, final EntityPermission entityPermission) {
222        WorkflowEntrancePartyType workflowEntrancePartyType = null;
223
224        if(eea == null || !eea.hasExecutionErrors()) {
225            workflowEntrancePartyType = workflowControl.getWorkflowEntrancePartyType(workflowEntrance, partyType, entityPermission);
226
227            if(workflowEntrancePartyType == null) {
228               var workflowEntranceDetail = workflowEntrance.getLastDetail();
229
230                handleExecutionError(UnknownWorkflowEntrancePartyTypeException.class, eea, ExecutionErrors.UnknownWorkflowEntrancePartyType.name(),
231                        workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName(),
232                        workflowEntranceDetail.getWorkflowEntranceName(), partyType.getPartyTypeName());
233            }
234        }
235
236        return workflowEntrancePartyType;
237    }
238
239    public WorkflowEntrancePartyType getWorkflowEntrancePartyType(final ExecutionErrorAccumulator eea, final WorkflowEntrance workflowEntrance,
240            final PartyType partyType) {
241        return getWorkflowEntrancePartyType(eea, workflowEntrance, partyType, EntityPermission.READ_ONLY);
242    }
243
244    public WorkflowEntrancePartyType getWorkflowEntrancePartyTypeForUpdate(final ExecutionErrorAccumulator eea, final WorkflowEntrance workflowEntrance,
245            final PartyType partyType) {
246        return getWorkflowEntrancePartyType(eea, workflowEntrance, partyType, EntityPermission.READ_WRITE);
247    }
248
249    public WorkflowEntrancePartyType getWorkflowEntrancePartyTypeByName(final ExecutionErrorAccumulator eea, final String workflowName,
250            final String workflowEntranceName, final String partyTypeName, final EntityPermission entityPermission) {
251        var workflowEntrance = getWorkflowEntranceByName(eea, workflowName, workflowEntranceName);
252        var partyType = partyLogic.getPartyTypeByName(eea, partyTypeName);
253
254        return getWorkflowEntrancePartyType(eea, workflowEntrance, partyType, entityPermission);
255    }
256
257    public WorkflowEntrancePartyType getWorkflowEntrancePartyTypeByName(final ExecutionErrorAccumulator eea, final String workflowName,
258            final String workflowEntranceName, final String partyTypeName) {
259        return getWorkflowEntrancePartyTypeByName(eea, workflowName, workflowEntranceName, partyTypeName,
260                EntityPermission.READ_ONLY);
261    }
262
263
264    public WorkflowEntrancePartyType getWorkflowEntrancePartyTypeByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName,
265            final String workflowEntranceName, final String partyTypeName) {
266        return getWorkflowEntrancePartyTypeByName(eea, workflowName, workflowEntranceName, partyTypeName,
267                EntityPermission.READ_WRITE);
268    }
269    
270    public WorkflowEntranceSecurityRole getWorkflowEntranceSecurityRoleByName(final ExecutionErrorAccumulator eea, final String workflowName,
271            final String workflowEntranceName, final String partyTypeName, final String securityRoleName,
272            final EntityPermission entityPermission) {
273        var workflowEntrance = getWorkflowEntranceByName(eea, workflowName, workflowEntranceName);
274        var partyType = partyLogic.getPartyTypeByName(eea, partyTypeName);
275        WorkflowEntranceSecurityRole workflowEntranceSecurityRole = null;
276
277        if(eea == null || !eea.hasExecutionErrors()) {
278            var securityRoleGroup = workflowEntrance.getLastDetail().getWorkflow().getLastDetail().getSecurityRoleGroup();
279
280            if(securityRoleGroup != null) {
281                var securityRole = securityRoleLogic.getSecurityRoleByName(eea, securityRoleGroup, securityRoleName);
282
283                if(eea == null || !eea.hasExecutionErrors()) {
284                    var workflowEntrancePartyType = getWorkflowEntrancePartyType(eea, workflowEntrance, partyType);
285
286                    if(eea == null || !eea.hasExecutionErrors()) {
287                        workflowEntranceSecurityRole = workflowControl.getWorkflowEntranceSecurityRole(workflowEntrancePartyType,
288                                securityRole, entityPermission);
289
290                        if(workflowEntranceSecurityRole == null) {
291                            var workflowEntranceDetail = workflowEntrance.getLastDetail();
292                            var securityRoleDetail = securityRole.getLastDetail();
293
294                            handleExecutionError(UnknownWorkflowEntranceSecurityRoleException.class, eea, ExecutionErrors.UnknownWorkflowEntranceSecurityRole.name(),
295                                    workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName(),
296                                    workflowEntranceDetail.getWorkflowEntranceName(), partyType.getPartyTypeName(),
297                                    securityRoleDetail.getSecurityRole().getLastDetail().getSecurityRoleName());
298                        }
299                    }
300                }
301            } else {
302                var workflowEntranceDetail = workflowEntrance.getLastDetail();
303
304                handleExecutionError(WorkflowMissingSecurityRoleGroupException.class, eea, ExecutionErrors.WorkflowMissingSecurityRoleGroup.name(),
305                        workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName());
306            }
307        }
308
309        return workflowEntranceSecurityRole;
310    }
311
312    public WorkflowEntranceSecurityRole getWorkflowEntranceSecurityRoleByName(final ExecutionErrorAccumulator eea, final String workflowName,
313            final String workflowEntranceName, final String partyTypeName, final String securityRoleName) {
314        return getWorkflowEntranceSecurityRoleByName(eea, workflowName, workflowEntranceName, partyTypeName, securityRoleName,
315                EntityPermission.READ_ONLY);
316    }
317
318
319    public WorkflowEntranceSecurityRole getWorkflowEntranceSecurityRoleByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName,
320            final String workflowEntranceName, final String partyTypeName, final String securityRoleName) {
321        return getWorkflowEntranceSecurityRoleByName(eea, workflowName, workflowEntranceName, partyTypeName, securityRoleName,
322                EntityPermission.READ_WRITE);
323    }
324    
325    public WorkflowEntranceSelector getWorkflowEntranceSelectorByName(final ExecutionErrorAccumulator eea, final String workflowName,
326            final String workflowEntranceName, final String selectorName, final EntityPermission entityPermission) {
327        var workflowEntrance = getWorkflowEntranceByName(eea, workflowName, workflowEntranceName);
328        WorkflowEntranceSelector workflowEntranceSelector = null;
329
330        if(eea == null || !eea.hasExecutionErrors()) {
331            var selectorType = workflowEntrance.getLastDetail().getWorkflow().getLastDetail().getSelectorType();
332
333            if(selectorType != null) {
334                var selector = selectorLogic.getSelectorByName(eea, selectorType, selectorName);
335
336                if(eea == null || !eea.hasExecutionErrors()) {
337                    workflowEntranceSelector = workflowControl.getWorkflowEntranceSelector(workflowEntrance,
338                            selector, entityPermission);
339
340                    if(workflowEntranceSelector == null) {
341                        var workflowEntranceDetail = workflowEntrance.getLastDetail();
342                        var selectorDetail = selector.getLastDetail();
343
344                        handleExecutionError(UnknownWorkflowEntranceSelectorException.class, eea, ExecutionErrors.UnknownWorkflowEntranceSelector.name(),
345                                workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName(),
346                                workflowEntranceDetail.getWorkflowEntranceName(),
347                                selectorDetail.getSelector().getLastDetail().getSelectorName());
348                    }
349                }
350            } else {
351                var workflowEntranceDetail = workflowEntrance.getLastDetail();
352
353                handleExecutionError(WorkflowMissingSelectorTypeException.class, eea, ExecutionErrors.WorkflowMissingSelectorType.name(),
354                        workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName());
355            }
356        }
357
358        return workflowEntranceSelector;
359    }
360
361    public WorkflowEntranceSelector getWorkflowEntranceSelectorByName(final ExecutionErrorAccumulator eea, final String workflowName,
362            final String workflowEntranceName, final String selectorName) {
363        return getWorkflowEntranceSelectorByName(eea, workflowName, workflowEntranceName, selectorName,
364                EntityPermission.READ_ONLY);
365    }
366
367
368    public WorkflowEntranceSelector getWorkflowEntranceSelectorByNameForUpdate(final ExecutionErrorAccumulator eea, final String workflowName,
369            final String workflowEntranceName, final String selectorName) {
370        return getWorkflowEntranceSelectorByName(eea, workflowName, workflowEntranceName, selectorName,
371                EntityPermission.READ_WRITE);
372    }
373
374    public WorkflowStep getEntranceWorkflowStep(final ExecutionErrorAccumulator eea, final String entranceWorkflowName,
375            final String entranceWorkflowStepName) {
376        return workflowStepLogic.getWorkflowStepByName(
377                UnknownEntranceWorkflowNameException.class, ExecutionErrors.UnknownEntranceWorkflowName,
378                UnknownEntranceWorkflowStepNameException.class, ExecutionErrors.UnknownEntranceWorkflowStepName,
379                eea, entranceWorkflowName, entranceWorkflowStepName);
380    }
381
382    public WorkflowEntranceStep getWorkflowEntranceStep(final ExecutionErrorAccumulator eea,
383            WorkflowEntrance workflowEntrance, WorkflowStep entranceWorkflowStep) {
384        var workflowEntranceStep = workflowControl.getWorkflowEntranceStep(workflowEntrance, entranceWorkflowStep);
385
386        if(workflowEntranceStep == null) {
387            var workflowEntranceDetail = workflowEntrance.getLastDetail();
388            var entranceWorkflowStepDetail = entranceWorkflowStep.getLastDetail();
389
390            handleExecutionError(UnknownWorkflowEntranceStepException.class, eea, ExecutionErrors.UnknownWorkflowEntranceStep.name(),
391                    workflowEntranceDetail.getWorkflow().getLastDetail().getWorkflowName(),
392                    workflowEntranceDetail.getWorkflowEntranceName(),
393                    entranceWorkflowStepDetail.getWorkflow().getLastDetail().getWorkflowName(),
394                    entranceWorkflowStepDetail.getWorkflowStepName());
395        }
396
397        return workflowEntranceStep;
398    }
399
400    public WorkflowEntranceStep getWorkflowEntranceStepByName(final ExecutionErrorAccumulator eea,
401            final String workflowName, final String workflowEntranceName, final String entranceWorkflowName,
402            final String entranceWorkflowStepName) {
403        var workflowEntrance = getWorkflowEntranceByName(eea, workflowName, workflowEntranceName);
404        var entranceWorkflowStep = getEntranceWorkflowStep(eea, entranceWorkflowName, entranceWorkflowStepName);
405        WorkflowEntranceStep workflowEntranceStep = null;
406
407        if(eea == null || !eea.hasExecutionErrors()) {
408            workflowEntranceStep = getWorkflowEntranceStep(eea, workflowEntrance, entranceWorkflowStep);
409        }
410
411        return workflowEntranceStep;
412    }
413    
414}