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