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.batch.server.logic;
018
019import com.echothree.model.control.batch.common.exception.MissingDefaultWorkflowEntranceException;
020import com.echothree.model.control.batch.common.exception.UnknownBatchAliasTypeNameException;
021import com.echothree.model.control.batch.common.exception.UnknownBatchNameException;
022import com.echothree.model.control.batch.common.exception.UnknownBatchSequenceException;
023import com.echothree.model.control.batch.common.exception.UnknownBatchSequenceTypeException;
024import com.echothree.model.control.batch.common.exception.UnknownBatchTypeEntityTypeException;
025import com.echothree.model.control.batch.common.exception.UnknownBatchTypeNameException;
026import com.echothree.model.control.batch.server.control.BatchControl;
027import com.echothree.model.control.core.server.control.EntityInstanceControl;
028import com.echothree.model.control.sequence.server.control.SequenceControl;
029import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic;
030import com.echothree.model.control.workflow.server.control.WorkflowControl;
031import com.echothree.model.data.batch.server.entity.Batch;
032import com.echothree.model.data.batch.server.entity.BatchAliasType;
033import com.echothree.model.data.batch.server.entity.BatchEntity;
034import com.echothree.model.data.batch.server.entity.BatchType;
035import com.echothree.model.data.core.server.entity.EntityInstance;
036import com.echothree.model.data.sequence.server.entity.Sequence;
037import com.echothree.model.data.sequence.server.entity.SequenceType;
038import com.echothree.util.common.message.ExecutionErrors;
039import com.echothree.util.common.persistence.BasePK;
040import com.echothree.util.server.control.BaseLogic;
041import com.echothree.util.server.message.ExecutionErrorAccumulator;
042import com.echothree.util.server.persistence.BaseEntity;
043import com.echothree.util.server.persistence.EntityPermission;
044import javax.enterprise.context.ApplicationScoped;
045import javax.enterprise.inject.spi.CDI;
046import javax.inject.Inject;
047
048@ApplicationScoped
049public class BatchLogic
050        extends BaseLogic {
051
052    @Inject
053    BatchControl batchControl;
054
055    @Inject
056    EntityInstanceControl entityInstanceControl;
057
058    @Inject
059    SequenceControl sequenceControl;
060
061    @Inject
062    WorkflowControl workflowControl;
063
064    @Inject
065    SequenceGeneratorLogic sequenceGeneratorLogic;
066
067    protected BatchLogic() {
068        super();
069    }
070
071    public static BatchLogic getInstance() {
072        return CDI.current().select(BatchLogic.class).get();
073    }
074
075    public SequenceType getBatchSequenceType(final ExecutionErrorAccumulator eea, final BatchType batchType) {
076        SequenceType sequenceType;
077        var parentBatchType = batchType;
078
079        do {
080            var batchTypeDetail = parentBatchType.getLastDetail();
081
082            sequenceType = batchTypeDetail.getBatchSequenceType();
083
084            if(sequenceType == null) {
085                parentBatchType = batchTypeDetail.getParentBatchType();
086            } else {
087                break;
088            }
089        } while(parentBatchType != null);
090
091        if(sequenceType == null) {
092            sequenceType = sequenceControl.getDefaultSequenceType();
093        }
094
095        if(sequenceType == null) {
096            handleExecutionError(UnknownBatchSequenceTypeException.class, eea, ExecutionErrors.UnknownBatchSequenceType.name(),
097                    batchType.getLastDetail().getBatchTypeName());
098        }
099
100        return sequenceType;
101    }
102
103    public Sequence getBatchSequence(final ExecutionErrorAccumulator eea, final BatchType batchType) {
104        Sequence sequence = null;
105        var sequenceType = getBatchSequenceType(eea, batchType);
106
107        if(eea == null || !eea.hasExecutionErrors()) {
108            sequence = sequenceControl.getDefaultSequence(sequenceType);
109        }
110
111        if(sequence == null) {
112            handleExecutionError(UnknownBatchSequenceException.class, eea, ExecutionErrors.UnknownBatchSequence.name(),
113                    batchType.getLastDetail().getBatchTypeName());
114        }
115
116        return sequence;
117    }
118
119    public String getBatchName(final ExecutionErrorAccumulator eea, final BatchType batchType) {
120        String batchName = null;
121        var sequence = getBatchSequence(eea, batchType);
122
123        if(eea == null || !eea.hasExecutionErrors()) {
124            batchName = sequenceGeneratorLogic.getNextSequenceValue(sequence);
125        }
126
127        return batchName;
128    }
129
130    public Batch createBatch(final ExecutionErrorAccumulator eea, final String batchTypeName, final BasePK createdBy) {
131        var batchType = batchControl.getBatchTypeByName(batchTypeName);
132        Batch batch = null;
133
134        if(batchType != null) {
135            var batchName = getBatchName(eea, batchType);
136
137            if(eea == null || !eea.hasExecutionErrors()) {
138                var batchTypeDetail = batchType.getLastDetail();
139                var workflowEntrance = batchTypeDetail.getBatchWorkflowEntrance();
140
141                if(workflowEntrance == null) {
142                    var workflow = batchTypeDetail.getBatchWorkflow();
143
144                    if(workflow != null) {
145                        workflowEntrance = workflowControl.getDefaultWorkflowEntrance(workflow);
146
147                        if(workflowEntrance == null) {
148                            handleExecutionError(MissingDefaultWorkflowEntranceException.class, eea, ExecutionErrors.MissingDefaultWorkflowEntrance.name(),
149                                    workflow.getLastDetail().getWorkflowName());
150                        }
151                    }
152                }
153
154                if(eea == null || !eea.hasExecutionErrors()) {
155                    batch = batchControl.createBatch(batchType, batchName, createdBy);
156
157                    if(workflowEntrance != null) {
158                        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(batch.getPrimaryKey());
159
160                        // TODO: A WorkEffort should be created for the batch entry, if it's manually entered.
161                        workflowControl.addEntityToWorkflow(workflowEntrance, entityInstance, null, null, createdBy);
162                    }
163                }
164            }
165        } else {
166            handleExecutionError(UnknownBatchTypeNameException.class, eea, ExecutionErrors.UnknownBatchTypeName.name(), batchTypeName);
167        }
168
169        return batch;
170    }
171
172    public void deleteBatch(final ExecutionErrorAccumulator eea, final Batch batch, final BasePK deletedBy) {
173        batchControl.deleteBatch(batch, deletedBy);
174    }
175
176    public BatchType getBatchTypeByName(final ExecutionErrorAccumulator eea, final String batchTypeName) {
177        var batchType = batchControl.getBatchTypeByName(batchTypeName);
178
179        if(batchType == null) {
180            handleExecutionError(UnknownBatchTypeNameException.class, eea, ExecutionErrors.UnknownBatchTypeName.name(), batchTypeName);
181        }
182
183        return batchType;
184    }
185
186    public BatchAliasType getBatchAliasTypeByName(final ExecutionErrorAccumulator eea, final BatchType batchType, final String batchAliasTypeName) {
187        var batchAliasType = batchControl.getBatchAliasTypeByName(batchType, batchAliasTypeName);
188
189        if(batchAliasType == null) {
190            handleExecutionError(UnknownBatchAliasTypeNameException.class, eea, ExecutionErrors.UnknownBatchAliasTypeName.name(),
191                    batchType.getLastDetail().getBatchTypeName(), batchAliasTypeName);
192        }
193
194        return batchAliasType;
195    }
196
197    public Batch getBatchByName(final ExecutionErrorAccumulator eea, final BatchType batchType, final String batchName,
198            final EntityPermission entityPermission) {
199        var batch = batchControl.getBatchByName(batchType, batchName, entityPermission);
200
201        if(batch == null) {
202            handleExecutionError(UnknownBatchNameException.class, eea, ExecutionErrors.UnknownBatchName.name(),
203                    batchType.getLastDetail().getBatchTypeName(), batchName);
204        }
205
206        return batch;
207    }
208
209    public Batch getBatchByName(final ExecutionErrorAccumulator eea, final BatchType batchType, final String batchName) {
210        return getBatchByName(eea, batchType, batchName, EntityPermission.READ_ONLY);
211    }
212
213    public Batch getBatchByName(final ExecutionErrorAccumulator eea, final String batchTypeName, final String batchName,
214            final EntityPermission entityPermission) {
215        var batchType = getBatchTypeByName(eea, batchTypeName);
216        Batch batch = null;
217
218        if(eea == null || !eea.hasExecutionErrors()) {
219            batch = getBatchByName(eea, batchType, batchName, entityPermission);
220        }
221
222        return batch;
223    }
224
225    public Batch getBatchByName(final ExecutionErrorAccumulator eea, final String batchTypeName, final String batchName) {
226        return getBatchByName(eea, batchTypeName, batchName, EntityPermission.READ_ONLY);
227    }
228
229    public Batch getBatchByNameForUpdate(final ExecutionErrorAccumulator eea, final String batchTypeName, final String batchName) {
230        return getBatchByName(eea, batchTypeName, batchName, EntityPermission.READ_WRITE);
231    }
232
233    public BatchEntity createBatchEntity(final ExecutionErrorAccumulator eea, final BaseEntity baseEntity, final Batch batch, final BasePK createdBy) {
234        return createBatchEntity(eea, getEntityInstanceByBaseEntity(baseEntity), batch, createdBy);
235    }
236    
237    public BatchEntity createBatchEntity(final ExecutionErrorAccumulator eea, final EntityInstance entityInstance, final Batch batch, final BasePK createdBy) {
238        var batchType = batch.getLastDetail().getBatchType();
239        BatchEntity batchEntity = null;
240
241        if(batchControl.countBatchTypeEntityTypesByBatchType(batchType) != 0) {
242            var entityType = entityInstance.getEntityType();
243
244            if(!batchControl.getBatchTypeEntityTypeExists(batchType, entityType)) {
245                var entityTypeDetail = entityType.getLastDetail();
246
247                handleExecutionError(UnknownBatchTypeEntityTypeException.class, eea, ExecutionErrors.UnknownBatchTypeEntityType.name(),
248                        batchType.getLastDetail().getBatchTypeName(), entityTypeDetail.getComponentVendor().getLastDetail().getComponentVendorName(),
249                        entityTypeDetail.getEntityTypeName());
250            }
251        }
252
253        if(!hasExecutionErrors(eea)) {
254            batchEntity = batchControl.createBatchEntity(entityInstance, batch, createdBy);
255        }
256
257        return batchEntity;
258    }
259
260    public boolean batchEntityExists(final BaseEntity baseEntity, final Batch batch) {
261        return batchEntityExists(getEntityInstanceByBaseEntity(baseEntity), batch);
262    }
263    
264    public boolean batchEntityExists(final EntityInstance entityInstance, final Batch batch) {
265        return batchControl.batchEntityExists(entityInstance, batch);
266    }
267    
268    public void deleteBatchEntity(BatchEntity batchEntity, BasePK deletedBy) {
269        batchControl.deleteBatchEntity(batchEntity, deletedBy);
270    }
271
272}