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.model.control.core.common.ComponentVendors;
020import com.echothree.model.control.core.common.EntityTypes;
021import com.echothree.model.control.order.server.trigger.OrderTrigger;
022import com.echothree.model.control.printer.server.trigger.PrinterGroupJobTrigger;
023import com.echothree.model.control.training.server.trigger.PartyTrainingClassTrigger;
024import com.echothree.model.control.workflow.server.control.WorkflowControl;
025import com.echothree.model.control.workflow.server.trigger.EntityTypeTrigger;
026import com.echothree.model.data.core.server.entity.EntityInstance;
027import com.echothree.model.data.core.server.entity.EntityTypeDetail;
028import com.echothree.model.data.party.common.pk.PartyPK;
029import com.echothree.model.data.workflow.server.entity.WorkflowEntityStatus;
030import com.echothree.model.data.workflow.server.entity.WorkflowTrigger;
031import com.echothree.model.data.workflow.server.factory.WorkflowTriggerFactory;
032import com.echothree.util.common.message.ExecutionErrors;
033import com.echothree.util.server.message.ExecutionErrorAccumulator;
034import com.echothree.util.server.persistence.EntityPermission;
035import com.echothree.util.server.persistence.Session;
036
037public class WorkflowTriggerLogic {
038    
039    private WorkflowTriggerLogic() {
040        super();
041    }
042    
043    private static class WorkflowTriggerLogicHolder {
044        static WorkflowTriggerLogic instance = new WorkflowTriggerLogic();
045    }
046    
047    public static WorkflowTriggerLogic getInstance() {
048        return WorkflowTriggerLogicHolder.instance;
049    }
050    
051    // TODO: configure using a property file.
052    private EntityTypeTrigger locateTrigger(final ExecutionErrorAccumulator eea, final String componentVendorName, final String entityTypeName) {
053        EntityTypeTrigger result = null;
054        
055        if(componentVendorName.equals(ComponentVendors.ECHO_THREE.name())) {
056            if(entityTypeName.equals(EntityTypes.PartyTrainingClass.name())) {
057                result = new PartyTrainingClassTrigger();
058            } else if(entityTypeName.equals(EntityTypes.PrinterGroupJob.name())) {
059                result = new PrinterGroupJobTrigger();
060            } else if(entityTypeName.equals(EntityTypes.Order.name())) {
061                result = new OrderTrigger();
062            }
063        }
064        
065        if(result == null) {
066            eea.addExecutionError(ExecutionErrors.UnknownGeneralTrigger.name(), componentVendorName, entityTypeName);
067        }
068        
069        return result;
070    }
071    
072    private void processWorkflowTrigger(final Session session, final ExecutionErrorAccumulator eea, final WorkflowTrigger workflowTrigger, final PartyPK triggeredBy) {
073        WorkflowEntityStatus workflowEntityStatus = workflowTrigger.getWorkflowEntityStatusForUpdate();
074        EntityInstance entityInstance = workflowEntityStatus.getEntityInstance();
075        EntityTypeDetail entityTypeDetail = entityInstance.getEntityType().getLastDetail();
076        String entityTypeName = entityTypeDetail.getEntityTypeName();
077        String componentVendorName = entityTypeDetail.getComponentVendor().getLastDetail().getComponentVendorName();
078        EntityTypeTrigger entityTypeTrigger = locateTrigger(eea, componentVendorName, entityTypeName);
079        
080        if(eea == null || !eea.hasExecutionErrors()) {
081            entityTypeTrigger.handleTrigger(session, eea, workflowEntityStatus, triggeredBy);
082        }
083    }
084    
085    public void processWorkflowTriggers(final Session session, final ExecutionErrorAccumulator eea, final PartyPK triggeredBy) {
086        var workflowControl = Session.getModelController(WorkflowControl.class);
087        long remainingTime = (long) 1 * 60 * 1000; // 1 minute
088        
089        for(WorkflowTrigger workflowTrigger : workflowControl.getWorkflowTriggersByTriggerTime(session.START_TIME_LONG)) {
090            Boolean errorsOccurred = workflowTrigger.getErrorsOccurred();
091
092            if(errorsOccurred == null || errorsOccurred == false) {
093                long startTime = System.currentTimeMillis();
094
095                workflowTrigger = WorkflowTriggerFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, workflowTrigger.getPrimaryKey());
096                processWorkflowTrigger(session, eea, workflowTrigger, triggeredBy);
097
098                if(eea.hasExecutionErrors()) {
099                    workflowTrigger.setErrorsOccurred(Boolean.TRUE);
100                    break;
101                } else {
102                    remainingTime -= System.currentTimeMillis() - startTime;
103                    if(remainingTime < 0) {
104                        break;
105                    }
106                }
107            }
108        }
109    }
110
111}