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.security.server.logic;
018
019import com.echothree.model.control.security.common.exception.UnknownPartySecurityRoleTemplateNameException;
020import com.echothree.model.control.security.server.control.SecurityControl;
021import com.echothree.model.control.training.common.training.PartyTrainingClassStatusConstants;
022import com.echothree.model.control.training.server.control.TrainingControl;
023import com.echothree.model.control.training.server.logic.PartyTrainingClassLogic;
024import com.echothree.model.control.training.server.logic.PartyTrainingClassLogic.PreparedPartyTrainingClass;
025import com.echothree.model.data.security.server.entity.PartySecurityRoleTemplate;
026import com.echothree.model.data.security.server.entity.PartySecurityRoleTemplateRole;
027import com.echothree.model.data.security.server.entity.PartySecurityRoleTemplateTrainingClass;
028import com.echothree.model.data.security.server.entity.SecurityRole;
029import com.echothree.model.data.training.server.entity.TrainingClass;
030import com.echothree.util.common.message.ExecutionErrors;
031import com.echothree.util.common.persistence.BasePK;
032import com.echothree.util.server.control.BaseLogic;
033import com.echothree.util.server.message.ExecutionErrorAccumulator;
034import com.echothree.util.server.persistence.EntityPermission;
035import com.echothree.util.server.persistence.Session;
036import java.util.HashSet;
037import java.util.List;
038import java.util.Set;
039import javax.enterprise.context.ApplicationScoped;
040import javax.enterprise.inject.spi.CDI;
041import javax.inject.Inject;
042
043@ApplicationScoped
044public class PartySecurityRoleTemplateLogic
045        extends BaseLogic {
046
047    @Inject
048    protected SecurityControl securityControl;
049
050    @Inject
051    protected TrainingControl trainingControl;
052
053    @Inject
054    PartyTrainingClassLogic partyTrainingClassLogic;
055
056    protected PartySecurityRoleTemplateLogic() {
057        super();
058    }
059
060    public static PartySecurityRoleTemplateLogic getInstance() {
061        return CDI.current().select(PartySecurityRoleTemplateLogic.class).get();
062    }
063
064    // --------------------------------------------------------------------------------
065    //   Party Security Role Templates
066    // --------------------------------------------------------------------------------
067
068    public PartySecurityRoleTemplate getPartySecurityRoleTemplateByName(final ExecutionErrorAccumulator eea, final String partySecurityRoleTemplateName,
069            final EntityPermission entityPermission) {
070        var partySecurityRoleTemplate = securityControl.getPartySecurityRoleTemplateByName(partySecurityRoleTemplateName, entityPermission);
071
072        if(partySecurityRoleTemplate == null) {
073            handleExecutionError(UnknownPartySecurityRoleTemplateNameException.class, eea, ExecutionErrors.UnknownPartySecurityRoleTemplateName.name(), partySecurityRoleTemplateName);
074        }
075
076        return partySecurityRoleTemplate;
077    }
078
079    public PartySecurityRoleTemplate getPartySecurityRoleTemplateByName(final ExecutionErrorAccumulator eea, final String partySecurityRoleTemplateName) {
080        return getPartySecurityRoleTemplateByName(eea, partySecurityRoleTemplateName, EntityPermission.READ_ONLY);
081    }
082
083    public PartySecurityRoleTemplate getPartySecurityRoleTemplateByNameForUpdate(final ExecutionErrorAccumulator eea, final String partySecurityRoleTemplateName) {
084        return getPartySecurityRoleTemplateByName(eea, partySecurityRoleTemplateName, EntityPermission.READ_WRITE);
085    }
086
087    // --------------------------------------------------------------------------------
088    //   Party Security Role Template Roles
089    // --------------------------------------------------------------------------------
090
091    public PartySecurityRoleTemplateRole createPartySecurityRoleTemplateRole(final PartySecurityRoleTemplate partySecurityRoleTemplate,
092            final SecurityRole securityRole, final BasePK createdBy) {
093        var partySecurityRoleTemplateRole = securityControl.createPartySecurityRoleTemplateRole(partySecurityRoleTemplate,
094                securityRole, createdBy);
095
096        // Add SecurityRole to any Parties that are currently assigned to the PartySecurityRoleTemplate.
097        var partySecurityRoleTemplateUses = securityControl.getPartySecurityRoleTemplateUsesByPartySecurityRoleTemplate(partySecurityRoleTemplate);
098        partySecurityRoleTemplateUses.stream().map((partySecurityRoleTemplateUse) -> partySecurityRoleTemplateUse.getParty()).filter((party) -> (securityControl.getPartySecurityRole(party, securityRole) == null)).forEach((party) -> {
099            securityControl.createPartySecurityRole(party, securityRole, createdBy);
100        });
101
102        return partySecurityRoleTemplateRole;
103    }
104
105    public void deletePartySecurityRoleTemplateRole(final PartySecurityRoleTemplateRole partySecurityRoleTemplateRole, final BasePK deletedBy) {
106        var partySecurityRoleTemplate = partySecurityRoleTemplateRole.getPartySecurityRoleTemplate();
107
108        securityControl.deletePartySecurityRoleTemplateRole(partySecurityRoleTemplateRole, deletedBy);
109
110        // Remove SecurityRole from any Parties that may be assigned to its PartySecurityRoleTemplate.
111        var partySecurityRoleTemplateUses = securityControl.getPartySecurityRoleTemplateUsesByPartySecurityRoleTemplate(partySecurityRoleTemplate);
112        if(partySecurityRoleTemplateUses.size() > 0) {
113            var securityRole = partySecurityRoleTemplateRole.getSecurityRole();
114
115            partySecurityRoleTemplateUses.stream().map((partySecurityRoleTemplateUse) -> partySecurityRoleTemplateUse.getParty()).map((party) -> securityControl.getPartySecurityRoleForUpdate(party, securityRole)).filter((partySecurityRole) -> (partySecurityRole != null)).forEach((partySecurityRole) -> {
116                securityControl.deletePartySecurityRole(partySecurityRole, deletedBy);
117            });
118        }
119    }
120    
121    public void deletePartySecurityRoleTemplateRoles(final List<PartySecurityRoleTemplateRole> partySecurityRoleTemplateRoles, final BasePK deletedBy) {
122        partySecurityRoleTemplateRoles.forEach((partySecurityRoleTemplateRole) -> 
123                deletePartySecurityRoleTemplateRole(partySecurityRoleTemplateRole, deletedBy)
124        );
125    }
126
127    public void deletePartySecurityRoleTemplateRoleByPartySecurityRoleTemplate(final PartySecurityRoleTemplate partySecurityRoleTemplate, final BasePK deletedBy) {
128        deletePartySecurityRoleTemplateRoles(securityControl.getPartySecurityRoleTemplateRolesForUpdate(partySecurityRoleTemplate), deletedBy);
129    }
130
131    public void deletePartySecurityRoleTemplateRolesBySecurityRole(final SecurityRole securityRole, final BasePK deletedBy) {
132        deletePartySecurityRoleTemplateRoles(securityControl.getPartySecurityRoleTemplateRolesBySecurityRoleForUpdate(securityRole), deletedBy);
133    }
134
135    // --------------------------------------------------------------------------------
136    //   Party Security Role Template Training Classes
137    // --------------------------------------------------------------------------------
138
139    public static class PreparedPartySecurityRoleTemplateTrainingClass {
140
141        private PartySecurityRoleTemplate partySecurityRoleTemplate;
142        private TrainingClass trainingClass;
143        private Set<PreparedPartyTrainingClass> preparedPartyTrainingClasses;
144
145        public PartySecurityRoleTemplate getPartySecurityRoleTemplate() {
146            return partySecurityRoleTemplate;
147        }
148
149        public void setPartySecurityRoleTemplate(PartySecurityRoleTemplate partySecurityRoleTemplate) {
150            this.partySecurityRoleTemplate = partySecurityRoleTemplate;
151        }
152
153        public TrainingClass getTrainingClass() {
154            return trainingClass;
155        }
156
157        public void setTrainingClass(TrainingClass trainingClass) {
158            this.trainingClass = trainingClass;
159        }
160
161        public Set<PreparedPartyTrainingClass> getPreparedPartyTrainingClasses() {
162            return preparedPartyTrainingClasses;
163        }
164
165        public void setPreparedPartyTrainingClasses(Set<PreparedPartyTrainingClass> preparedPartyTrainingClasses) {
166            this.preparedPartyTrainingClasses = preparedPartyTrainingClasses;
167        }
168
169    }
170
171    public PreparedPartySecurityRoleTemplateTrainingClass preparePartySecurityRoleTemplateTrainingClass(final ExecutionErrorAccumulator eea,
172            final PartySecurityRoleTemplate partySecurityRoleTemplate, final TrainingClass trainingClass) {
173        var preparedPartySecurityRoleTemplateTrainingClass = new PreparedPartySecurityRoleTemplateTrainingClass();
174
175        preparedPartySecurityRoleTemplateTrainingClass.setPartySecurityRoleTemplate(partySecurityRoleTemplate);
176        preparedPartySecurityRoleTemplateTrainingClass.setTrainingClass(trainingClass);
177
178        // If Party does not have a PartyTrainingClass for this TrainingClass in either ASSIGNED or TRAINING, then assign it to them.
179        var partySecurityRoleTemplateUses = securityControl.getPartySecurityRoleTemplateUsesByPartySecurityRoleTemplate(partySecurityRoleTemplate);
180        Set<PreparedPartyTrainingClass> preparedPartyTrainingClasses = new HashSet<>();
181        if(partySecurityRoleTemplateUses.size() > 0) {
182            for(var partySecurityRoleTemplateUse : partySecurityRoleTemplateUses) {
183                var party = partySecurityRoleTemplateUse.getParty();
184                var partyTrainingClasses = trainingControl.getPartyTrainingClassesByStatuses(party, trainingClass,
185                        PartyTrainingClassStatusConstants.WorkflowStep_ASSIGNED, PartyTrainingClassStatusConstants.WorkflowStep_TRAINING);
186
187                if(partyTrainingClasses.isEmpty()) {
188                    preparedPartyTrainingClasses.add(partyTrainingClassLogic.preparePartyTrainingClass(eea, party, trainingClass, null, null));
189                }
190
191                if(eea.hasExecutionErrors()) {
192                    break;
193                }
194            }
195        }
196
197        preparedPartySecurityRoleTemplateTrainingClass.setPreparedPartyTrainingClasses(preparedPartyTrainingClasses);
198
199        return preparedPartySecurityRoleTemplateTrainingClass;
200    }
201
202    public PartySecurityRoleTemplateTrainingClass createPartySecurityRoleTemplateTrainingClass(final Session session,
203            final PreparedPartySecurityRoleTemplateTrainingClass preparedPartySecurityRoleTemplateTrainingClass, final BasePK createdBy) {
204        var trainingClass = preparedPartySecurityRoleTemplateTrainingClass.getTrainingClass();
205        var partySecurityRoleTemplateTrainingClass = securityControl.createPartySecurityRoleTemplateTrainingClass(preparedPartySecurityRoleTemplateTrainingClass.partySecurityRoleTemplate,
206            trainingClass, createdBy);
207
208        // If Party does not have a PartyTrainingClass for this TrainingClass in either ASSIGNED or TRAINING, then assign it to them.
209        preparedPartySecurityRoleTemplateTrainingClass.getPreparedPartyTrainingClasses().forEach((preparedPartyTrainingClass) -> {
210            partyTrainingClassLogic.createPartyTrainingClass(session, preparedPartyTrainingClass, createdBy);
211        });
212
213        return partySecurityRoleTemplateTrainingClass;
214    }
215
216    public void deletePartySecurityRoleTemplateTrainingClass(final PartySecurityRoleTemplateTrainingClass partySecurityRoleTemplateTrainingClass,
217            final BasePK deletedBy) {
218        var partySecurityRoleTemplate = partySecurityRoleTemplateTrainingClass.getPartySecurityRoleTemplate();
219
220        securityControl.deletePartySecurityRoleTemplateTrainingClass(partySecurityRoleTemplateTrainingClass, deletedBy);
221
222        // If Party has a PartyTrainingClass in ASSIGNED status for this TrainingClass, then delete it.
223        var partySecurityRoleTemplateUses = securityControl.getPartySecurityRoleTemplateUsesByPartySecurityRoleTemplate(partySecurityRoleTemplate);
224        if(partySecurityRoleTemplateUses.size() > 0) {
225            var trainingClass = partySecurityRoleTemplateTrainingClass.getTrainingClass();
226
227            partySecurityRoleTemplateUses.stream().map((partySecurityRoleTemplateUse) -> partySecurityRoleTemplateUse.getParty()).map((party) -> trainingControl.getPartyTrainingClassesByStatusesForUpdate(party, trainingClass,
228                    PartyTrainingClassStatusConstants.WorkflowStep_ASSIGNED)).filter((partyTrainingClasses) -> (partyTrainingClasses.size() > 0)).forEach((partyTrainingClasses) -> {
229                        partyTrainingClasses.forEach((partyTrainingClass) -> {
230                            partyTrainingClassLogic.deletePartyTrainingClass(partyTrainingClass, deletedBy);
231                });
232            });
233        }
234    }
235
236    public void deletePartySecurityRoleTemplateTrainingClasses(final List<PartySecurityRoleTemplateTrainingClass> partySecurityRoleTemplateTrainingClasses,
237            final BasePK deletedBy) {
238        partySecurityRoleTemplateTrainingClasses.forEach((partySecurityRoleTemplateTrainingClass) -> 
239                deletePartySecurityRoleTemplateTrainingClass(partySecurityRoleTemplateTrainingClass, deletedBy)
240        );
241    }
242
243    public void deletePartySecurityRoleTemplateTrainingClassByPartySecurityRoleTemplate(final PartySecurityRoleTemplate partySecurityRoleTemplate,
244            final BasePK deletedBy) {
245        deletePartySecurityRoleTemplateTrainingClasses(securityControl.getPartySecurityRoleTemplateTrainingClassesForUpdate(partySecurityRoleTemplate), deletedBy);
246    }
247
248    public void deletePartySecurityRoleTemplateTrainingClassesByTrainingClass(final TrainingClass trainingClass, final BasePK deletedBy) {
249        deletePartySecurityRoleTemplateTrainingClasses(securityControl.getPartySecurityRoleTemplateTrainingClassesByTrainingClassForUpdate(trainingClass), deletedBy);
250    }
251
252}