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.training.server.logic;
018
019import com.echothree.control.user.training.common.spec.TrainingClassUniversalSpec;
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.training.common.exception.CannotDeleteTrainingClassInUseException;
025import com.echothree.model.control.training.common.exception.DuplicateTrainingClassNameException;
026import com.echothree.model.control.training.common.exception.UnknownDefaultTrainingClassException;
027import com.echothree.model.control.training.common.exception.UnknownTrainingClassNameException;
028import com.echothree.model.control.training.server.control.TrainingControl;
029import com.echothree.model.data.core.server.entity.MimeType;
030import com.echothree.model.data.party.server.entity.Language;
031import com.echothree.model.data.training.server.entity.TrainingClass;
032import com.echothree.model.data.workeffort.server.entity.WorkEffortScope;
033import com.echothree.util.common.message.ExecutionErrors;
034import com.echothree.util.common.persistence.BasePK;
035import com.echothree.util.server.control.BaseLogic;
036import com.echothree.util.server.message.ExecutionErrorAccumulator;
037import com.echothree.util.server.persistence.EntityPermission;
038import javax.enterprise.context.ApplicationScoped;
039import javax.enterprise.inject.spi.CDI;
040import javax.inject.Inject;
041
042@ApplicationScoped
043public class TrainingClassLogic
044        extends BaseLogic {
045
046    @Inject
047    private TrainingControl trainingControl;
048
049    protected TrainingClassLogic() {
050        super();
051    }
052
053    public static TrainingClassLogic getInstance() {
054        return CDI.current().select(TrainingClassLogic.class).get();
055    }
056
057    public TrainingClass createTrainingClass(final ExecutionErrorAccumulator eea, final String trainingClassName,
058            final Long estimatedReadingTime, final Long readingTimeAllowed, final Long estimatedTestingTime,
059            final Long testingTimeAllowed, final Long requiredCompletionTime, final WorkEffortScope workEffortScope,
060            final Integer defaultPercentageToPass, final Integer overallQuestionCount, final Long testingValidityTime,
061            final Long expiredRetentionTime, final Boolean alwaysReassignOnExpiration, final Boolean isDefault,
062            final Integer sortOrder, final Language language, final String description,
063            final MimeType overviewMimeType, final String overview,
064            final MimeType introductionMimeType, final String introduction,
065            final BasePK createdBy) {
066        var trainingClass = trainingControl.getTrainingClassByName(trainingClassName);
067
068        if(trainingClass == null) {
069            trainingClass = trainingControl.createTrainingClass(trainingClassName, estimatedReadingTime,
070                    readingTimeAllowed, estimatedTestingTime, testingTimeAllowed, requiredCompletionTime,
071                    workEffortScope, defaultPercentageToPass, overallQuestionCount, testingValidityTime,
072                    expiredRetentionTime, alwaysReassignOnExpiration, isDefault, sortOrder, createdBy);
073
074            if(description != null || overview != null || introduction != null) {
075                trainingControl.createTrainingClassTranslation(trainingClass, language, description,
076                        overviewMimeType, overview, introductionMimeType, introduction, createdBy);
077            }
078        } else {
079            handleExecutionError(DuplicateTrainingClassNameException.class, eea, ExecutionErrors.DuplicateTrainingClassName.name(), trainingClassName);
080        }
081
082        return trainingClass;
083    }
084
085    private TrainingClass getTrainingClassByName(final ExecutionErrorAccumulator eea, final String trainingClassName,
086            final boolean allowDefault, final EntityPermission entityPermission) {
087        TrainingClass trainingClass = null;
088
089        if(trainingClassName == null) {
090            if(allowDefault) {
091                trainingClass = trainingControl.getDefaultTrainingClass(entityPermission);
092
093                if(trainingClass == null) {
094                    handleExecutionError(UnknownDefaultTrainingClassException.class, eea, ExecutionErrors.UnknownDefaultTrainingClass.name());
095                }
096            } else {
097                handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
098            }
099        } else {
100            trainingClass = trainingControl.getTrainingClassByName(trainingClassName, entityPermission);
101
102            if(trainingClass == null) {
103                handleExecutionError(UnknownTrainingClassNameException.class, eea, ExecutionErrors.UnknownTrainingClassName.name(), trainingClassName);
104            }
105        }
106
107        return trainingClass;
108    }
109
110    public TrainingClass getTrainingClassByName(final ExecutionErrorAccumulator eea, final String trainingClassName,
111            final boolean allowDefault) {
112        return getTrainingClassByName(eea, trainingClassName, allowDefault, EntityPermission.READ_ONLY);
113    }
114
115    public TrainingClass getTrainingClassByNameForUpdate(final ExecutionErrorAccumulator eea, final String trainingClassName,
116            final boolean allowDefault) {
117        return getTrainingClassByName(eea, trainingClassName, allowDefault, EntityPermission.READ_WRITE);
118    }
119
120    public TrainingClass getTrainingClassByUniversalSpec(final ExecutionErrorAccumulator eea,
121            final TrainingClassUniversalSpec universalSpec, final boolean allowDefault, final EntityPermission entityPermission) {
122        TrainingClass trainingClass = null;
123        var trainingClassName = universalSpec.getTrainingClassName();
124        var parameterCount = (trainingClassName == null ? 0 : 1) + EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalSpec);
125
126        switch(parameterCount) {
127            case 0 -> trainingClass = getTrainingClassByName(eea, null, allowDefault, entityPermission);
128            case 1 -> {
129                if(trainingClassName == null) {
130                    var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalSpec,
131                            ComponentVendors.ECHO_THREE.name(), EntityTypes.TrainingClass.name());
132
133                    if(eea == null || !eea.hasExecutionErrors()) {
134                        trainingClass = trainingControl.getTrainingClassByEntityInstance(entityInstance, entityPermission);
135                    }
136                } else {
137                    trainingClass = getTrainingClassByName(eea, trainingClassName, false, entityPermission);
138                }
139            }
140            default ->
141                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
142        }
143
144        return trainingClass;
145    }
146
147    public TrainingClass getTrainingClassByUniversalSpec(final ExecutionErrorAccumulator eea,
148            final TrainingClassUniversalSpec universalSpec, final boolean allowDefault) {
149        return getTrainingClassByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
150    }
151
152    public TrainingClass getTrainingClassByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea,
153            final TrainingClassUniversalSpec universalSpec, final boolean allowDefault) {
154        return getTrainingClassByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
155    }
156
157    public void deleteTrainingClass(final ExecutionErrorAccumulator eea, final TrainingClass trainingClass,
158            final BasePK deletedBy) {
159        var trainingClassSectionCount = trainingControl.countTrainingClassSectionsByTrainingClass(trainingClass);
160
161        if(trainingClassSectionCount == 0) {
162            trainingControl.deleteTrainingClass(trainingClass, deletedBy);
163        } else {
164            handleExecutionError(CannotDeleteTrainingClassInUseException.class, eea, ExecutionErrors.CannotDeleteTrainingClassInUse.name(),
165                    trainingClass.getLastDetail().getTrainingClassName());
166        }
167    }
168    
169}