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.control.user.core.server.command;
018
019import com.echothree.control.user.core.common.edit.CoreEditFactory;
020import com.echothree.control.user.core.common.edit.EntityAliasEdit;
021import com.echothree.control.user.core.common.form.EditEntityAliasForm;
022import com.echothree.control.user.core.common.result.CoreResultFactory;
023import com.echothree.control.user.core.common.spec.EntityAliasSpec;
024import com.echothree.model.control.core.server.control.EntityAliasControl;
025import com.echothree.model.control.core.server.logic.EntityAliasTypeLogic;
026import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
027import com.echothree.model.control.party.common.PartyTypes;
028import com.echothree.model.control.security.common.SecurityRoleGroups;
029import com.echothree.model.control.security.common.SecurityRoles;
030import com.echothree.model.data.core.server.entity.EntityAlias;
031import com.echothree.model.data.user.common.pk.UserVisitPK;
032import com.echothree.util.common.command.BaseResult;
033import com.echothree.util.common.command.EditMode;
034import com.echothree.util.common.message.ExecutionErrors;
035import com.echothree.util.common.validation.FieldDefinition;
036import com.echothree.util.common.validation.FieldType;
037import com.echothree.util.server.control.BaseEditCommand;
038import com.echothree.util.server.control.CommandSecurityDefinition;
039import com.echothree.util.server.control.PartyTypeDefinition;
040import com.echothree.util.server.control.SecurityRoleDefinition;
041import com.echothree.util.server.persistence.PersistenceUtils;
042import java.util.List;
043import java.util.regex.Pattern;
044import javax.enterprise.context.Dependent;
045import javax.inject.Inject;
046
047@Dependent
048public class EditEntityAliasCommand
049        extends BaseEditCommand<EntityAliasSpec, EntityAliasEdit> {
050
051    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
052    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
053    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
054
055    static {
056        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
057                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
058                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
059                        new SecurityRoleDefinition(SecurityRoleGroups.EntityAlias.name(), SecurityRoles.Edit.name())
060                ))
061        ));
062
063        SPEC_FIELD_DEFINITIONS = List.of(
064                new FieldDefinition("EntityRef", FieldType.ENTITY_REF, false, null, null),
065                new FieldDefinition("Uuid", FieldType.UUID, false, null, null),
066                new FieldDefinition("EntityAliasTypeName", FieldType.ENTITY_NAME, false, null, null),
067                new FieldDefinition("EntityAliasTypeUuid", FieldType.UUID, false, null, null)
068        );
069
070        EDIT_FIELD_DEFINITIONS = List.of(
071                new FieldDefinition("Alias", FieldType.ENTITY_NAME, true, null, null)
072        );
073    }
074
075    @Inject
076    EntityAliasControl entityAliasControl;
077
078    @Inject
079    EntityAliasTypeLogic entityAliasTypeLogic;
080
081    @Inject
082    EntityInstanceLogic entityInstanceLogic;
083
084    /** Creates a new instance of EditEntityAliasCommand */
085    public EditEntityAliasCommand() {
086        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
087    }
088    
089    @Override
090    protected BaseResult execute() {
091        var result = CoreResultFactory.getEditEntityAliasResult();
092        var parameterCount = entityInstanceLogic.countPossibleEntitySpecs(spec);
093
094        if(parameterCount == 1) {
095            var entityInstance = entityInstanceLogic.getEntityInstance(this, spec);
096
097            if(!hasExecutionErrors()) {
098                var entityAliasTypeName = spec.getEntityAliasTypeName();
099                var entityAliasTypeUuid = spec.getEntityAliasTypeUuid();
100
101                parameterCount = (entityAliasTypeName == null ? 0 : 1) + (entityAliasTypeUuid == null ? 0 : 1);
102
103                if(parameterCount == 1) {
104                    var entityAliasType = entityAliasTypeName == null ?
105                            entityAliasTypeLogic.getEntityAliasTypeByUuid(this, entityAliasTypeUuid) :
106                            entityAliasTypeLogic.getEntityAliasTypeByName(this, entityInstance.getEntityType(), entityAliasTypeName);
107
108                    if(!hasExecutionErrors()) {
109                        if(entityInstance.getEntityType().equals(entityAliasType.getLastDetail().getEntityType())) {
110                            EntityAlias entityAlias = null;
111                            var basePK = PersistenceUtils.getInstance().getBasePKFromEntityInstance(entityInstance);
112
113                            if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
114                                entityAlias = entityAliasControl.getEntityAlias(entityInstance, entityAliasType);
115
116                                if(entityAlias != null) {
117                                    if(editMode.equals(EditMode.LOCK)) {
118                                        result.setEntityAlias(entityAliasControl.getEntityAliasTransfer(getUserVisit(), entityAlias));
119
120                                        if(lockEntity(basePK)) {
121                                            var edit = CoreEditFactory.getEntityAliasEdit();
122
123                                            result.setEdit(edit);
124                                            edit.setAlias(entityAlias.getAlias());
125                                        } else {
126                                            addExecutionError(ExecutionErrors.EntityLockFailed.name());
127                                        }
128                                    } else { // EditMode.ABANDON
129                                        unlockEntity(basePK);
130                                        basePK = null;
131                                    }
132                                } else {
133                                    addExecutionError(ExecutionErrors.UnknownEntityAlias.name(),
134                                            entityInstanceLogic.getEntityRefFromEntityInstance(entityInstance), entityAliasTypeName);
135                                }
136                            } else if(editMode.equals(EditMode.UPDATE)) {
137                                var validationPattern = entityAliasType.getLastDetail().getValidationPattern();
138                                var alias = edit.getAlias();
139
140                                if(validationPattern != null) {
141                                    var pattern = Pattern.compile(validationPattern);
142                                    var matcher = pattern.matcher(alias);
143
144                                    if(!matcher.matches()) {
145                                        addExecutionError(ExecutionErrors.InvalidAlias.name(), alias);
146                                    }
147                                }
148
149                                if(!hasExecutionErrors()) {
150                                    entityAlias = entityAliasControl.getEntityAliasForUpdate(entityInstance, entityAliasType);
151
152                                    if(entityAlias != null) {
153
154                                        var duplicateEntityAlias = entityAliasControl.getEntityAliasByEntityAliasTypeAndAlias(entityAliasType, alias);
155
156                                        if(duplicateEntityAlias != null && !entityAlias.equals(duplicateEntityAlias)) {
157                                            addExecutionError(ExecutionErrors.DuplicateEntityAlias.name(),
158                                                    entityInstanceLogic.getEntityRefFromEntityInstance(entityInstance),
159                                                    entityAliasType.getLastDetail().getEntityAliasTypeName(), alias);
160                                        } else {
161                                            if(lockEntityForUpdate(basePK)) {
162                                                try {
163                                                    var entityAliasValue = entityAliasControl.getEntityAliasValueForUpdate(entityAlias);
164
165                                                    entityAliasValue.setAlias(alias);
166
167                                                    entityAliasControl.updateEntityAliasFromValue(entityAliasValue, getPartyPK());
168                                                } finally {
169                                                    unlockEntity(basePK);
170                                                    basePK = null;
171                                                }
172                                            } else {
173                                                addExecutionError(ExecutionErrors.EntityLockStale.name());
174                                            }
175                                        }
176                                    } else {
177                                        addExecutionError(ExecutionErrors.UnknownEntityAlias.name(),
178                                                entityInstanceLogic.getEntityRefFromEntityInstance(entityInstance), entityAliasTypeName);
179                                    }
180                                }
181                            }
182
183                            if(basePK != null) {
184                                result.setEntityLock(getEntityLockTransfer(basePK));
185                            }
186
187                            if(entityAlias != null) {
188                                result.setEntityAlias(entityAliasControl.getEntityAliasTransfer(getUserVisit(), entityAlias));
189                            }
190                        } else {
191                            addExecutionError(ExecutionErrors.MismatchedEntityType.name());
192                        }
193                    }
194                } else {
195                    addExecutionError(ExecutionErrors.InvalidParameterCount.name());
196                }
197            }
198        } else {
199            addExecutionError(ExecutionErrors.InvalidParameterCount.name());
200        }
201
202        return result;
203    }
204    
205}