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