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