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.EntityAttributeEdit;
021import com.echothree.control.user.core.common.form.EditEntityAttributeForm;
022import com.echothree.control.user.core.common.result.CoreResultFactory;
023import com.echothree.control.user.core.common.result.EditEntityAttributeResult;
024import com.echothree.control.user.core.common.spec.EntityAttributeUniversalSpec;
025import com.echothree.model.control.core.common.EntityAttributeTypes;
026import com.echothree.model.control.core.server.logic.EntityAttributeLogic;
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.control.sequence.common.SequenceTypes;
031import com.echothree.model.control.sequence.server.control.SequenceControl;
032import com.echothree.model.control.sequence.server.logic.SequenceTypeLogic;
033import com.echothree.model.control.uom.server.logic.UnitOfMeasureTypeLogic;
034import com.echothree.model.data.core.server.entity.EntityAttribute;
035import com.echothree.model.data.sequence.server.entity.Sequence;
036import com.echothree.model.data.uom.server.entity.UnitOfMeasureType;
037import com.echothree.model.data.user.common.pk.UserVisitPK;
038import com.echothree.util.common.form.ValidationResult;
039import com.echothree.util.common.message.ExecutionErrors;
040import com.echothree.util.common.validation.FieldDefinition;
041import com.echothree.util.common.validation.FieldType;
042import com.echothree.util.server.control.BaseAbstractEditCommand;
043import com.echothree.util.server.control.CommandSecurityDefinition;
044import com.echothree.util.server.control.PartyTypeDefinition;
045import com.echothree.util.server.control.SecurityRoleDefinition;
046import com.echothree.util.server.validation.Validator;
047import java.util.List;
048import javax.enterprise.context.Dependent;
049import javax.inject.Inject;
050
051@Dependent
052public class EditEntityAttributeCommand
053        extends BaseAbstractEditCommand<EntityAttributeUniversalSpec, EntityAttributeEdit, EditEntityAttributeResult, EntityAttribute, EntityAttribute> {
054    
055    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
056    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
057    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
058    
059    static {
060        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
061                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
062                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
063                        new SecurityRoleDefinition(SecurityRoleGroups.EntityAttribute.name(), SecurityRoles.Edit.name())
064                ))
065        ));
066        
067        SPEC_FIELD_DEFINITIONS = List.of(
068                new FieldDefinition("EntityRef", FieldType.ENTITY_REF, false, null, null),
069                new FieldDefinition("Uuid", FieldType.UUID, false, null, null),
070                new FieldDefinition("ComponentVendorName", FieldType.ENTITY_NAME, false, null, null),
071                new FieldDefinition("EntityTypeName", FieldType.ENTITY_TYPE_NAME, false, null, null),
072                new FieldDefinition("EntityAttributeName", FieldType.ENTITY_NAME, false, null, null)
073        );
074        
075        EDIT_FIELD_DEFINITIONS = List.of(
076                new FieldDefinition("EntityAttributeName", FieldType.ENTITY_NAME, true, null, null),
077                new FieldDefinition("TrackRevisions", FieldType.BOOLEAN, true, null, null),
078                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
079                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
080        );
081    }
082
083    @Inject
084    SequenceControl sequenceControl;
085
086    @Inject
087    EntityAttributeLogic entityAttributeLogic;
088
089    @Inject
090    SequenceTypeLogic sequenceTypeLogic;
091
092    @Inject
093    UnitOfMeasureTypeLogic unitOfMeasureTypeLogic;
094
095    
096    /** Creates a new instance of EditEntityAttributeCommand */
097    public EditEntityAttributeCommand() {
098        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
099    }
100    
101    @Override
102    protected ValidationResult validateEdit(Validator validator) {
103        var validationResult = validator.validate(edit, getEditFieldDefinitions());
104        
105        if(!validationResult.getHasErrors()) {
106            entityAttribute = entityAttributeLogic.getEntityAttributeByUniversalSpec(this,
107                    spec);
108            
109            if(!hasExecutionErrors()) {
110                var entityAttributeType = entityAttribute.getLastDetail().getEntityAttributeType();
111    
112                validationResult = CreateEntityAttributeCommand.AdditionalEntityAttributeValidation(edit, validator, entityAttributeType);
113            }
114        }
115        
116        return validationResult;
117    }
118    
119    @Override
120    public EditEntityAttributeResult getResult() {
121        return CoreResultFactory.getEditEntityAttributeResult();
122    }
123
124    @Override
125    public EntityAttributeEdit getEdit() {
126        return CoreEditFactory.getEntityAttributeEdit();
127    }
128
129    EntityAttribute entityAttribute = null;
130    
131    @Override
132    public EntityAttribute getEntity(EditEntityAttributeResult result) {
133        entityAttribute = entityAttributeLogic.getEntityAttributeByUniversalSpec(this,
134                spec, editModeToEntityPermission(editMode));
135
136        return entityAttribute;
137    }
138
139    @Override
140    public EntityAttribute getLockEntity(EntityAttribute entityAttribute) {
141        return entityAttribute;
142    }
143
144    @Override
145    public void fillInResult(EditEntityAttributeResult result, EntityAttribute entityAttribute) {
146
147        result.setEntityAttribute(coreControl.getEntityAttributeTransfer(getUserVisit(), entityAttribute, null));
148    }
149
150    Sequence entityListItemSequence = null;
151    UnitOfMeasureType unitOfMeasureType = null;
152    
153    @Override
154    public void doLock(EntityAttributeEdit edit, EntityAttribute entityAttribute) {
155        var entityAttributeDescription = coreControl.getEntityAttributeDescription(entityAttribute, getPreferredLanguage());
156        var entityAttributeDetail = entityAttribute.getLastDetail();
157        var entityAttributeTypeName = entityAttribute.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
158        var entityAttributeType = EntityAttributeTypes.valueOf(entityAttributeTypeName);
159        
160        edit.setEntityAttributeName(entityAttributeDetail.getEntityAttributeName());
161        edit.setTrackRevisions(entityAttributeDetail.getTrackRevisions().toString());
162        edit.setSortOrder(entityAttributeDetail.getSortOrder().toString());
163
164        switch(entityAttributeType) {
165            case BLOB -> {
166                var entityAttributeBlob = coreControl.getEntityAttributeBlobForUpdate(entityAttribute);
167
168                edit.setCheckContentWebAddress(entityAttributeBlob.getCheckContentWebAddress().toString());
169            }
170            case STRING -> {
171                var entityAttributeString = coreControl.getEntityAttributeStringForUpdate(entityAttribute);
172
173                if(entityAttributeString != null) {
174                    edit.setValidationPattern(entityAttributeString.getValidationPattern());
175                }
176            }
177            case INTEGER -> {
178                var entityAttributeInteger = coreControl.getEntityAttributeIntegerForUpdate(entityAttribute);
179                var entityAttributeNumeric = coreControl.getEntityAttributeNumericForUpdate(entityAttribute);
180
181                if(entityAttributeInteger != null) {
182                    edit.setUpperLimitIntegerValue(entityAttributeInteger.getUpperLimitIntegerValue().toString());
183                    edit.setUpperRangeIntegerValue(entityAttributeInteger.getUpperRangeIntegerValue().toString());
184                    edit.setLowerRangeIntegerValue(entityAttributeInteger.getLowerRangeIntegerValue().toString());
185                    edit.setLowerLimitIntegerValue(entityAttributeInteger.getLowerLimitIntegerValue().toString());
186                }
187
188                if(entityAttributeNumeric != null) {
189                    unitOfMeasureType = entityAttributeNumeric.getUnitOfMeasureType();
190
191                    if(unitOfMeasureType != null) {
192                        var unitOfMeasureTypeDetail = unitOfMeasureType.getLastDetail();
193
194                        edit.setUnitOfMeasureKindName(unitOfMeasureTypeDetail.getUnitOfMeasureKind().getLastDetail().getUnitOfMeasureKindName());
195                        edit.setUnitOfMeasureTypeName(unitOfMeasureTypeDetail.getUnitOfMeasureTypeName());
196                    }
197                }
198            }
199            case LONG -> {
200                var entityAttributeLong = coreControl.getEntityAttributeLongForUpdate(entityAttribute);
201                var entityAttributeNumeric = coreControl.getEntityAttributeNumericForUpdate(entityAttribute);
202
203                if(entityAttributeLong != null) {
204                    edit.setUpperLimitLongValue(entityAttributeLong.getUpperLimitLongValue().toString());
205                    edit.setUpperRangeLongValue(entityAttributeLong.getUpperRangeLongValue().toString());
206                    edit.setLowerRangeLongValue(entityAttributeLong.getLowerRangeLongValue().toString());
207                    edit.setLowerLimitLongValue(entityAttributeLong.getLowerLimitLongValue().toString());
208                }
209
210                if(entityAttributeNumeric != null) {
211                    unitOfMeasureType = entityAttributeNumeric.getUnitOfMeasureType();
212
213                    if(unitOfMeasureType != null) {
214                        var unitOfMeasureTypeDetail = unitOfMeasureType.getLastDetail();
215
216                        edit.setUnitOfMeasureKindName(unitOfMeasureTypeDetail.getUnitOfMeasureKind().getLastDetail().getUnitOfMeasureKindName());
217                        edit.setUnitOfMeasureTypeName(unitOfMeasureTypeDetail.getUnitOfMeasureTypeName());
218                    }
219                }
220            }
221            case LISTITEM, MULTIPLELISTITEM -> {
222                var entityAttributeListItem = coreControl.getEntityAttributeListItemForUpdate(entityAttribute);
223
224                if(entityAttributeListItem != null) {
225                    entityListItemSequence = entityAttributeListItem.getEntityListItemSequence();
226
227                    edit.setEntityListItemSequenceName(entityListItemSequence == null ? null : entityListItemSequence.getLastDetail().getSequenceName());
228                }
229            }
230            default -> {
231            }
232        }
233        
234        if(entityAttributeDescription != null) {
235            edit.setDescription(entityAttributeDescription.getDescription());
236        }
237    }
238
239    @Override
240    public void canUpdate(EntityAttribute entityAttribute) {
241        var entityAttributeName = edit.getEntityAttributeName();
242        var duplicateEntityAttribute = coreControl.getEntityAttributeByName(entityAttribute.getLastDetail().getEntityType(),
243                entityAttributeName);
244
245        if(duplicateEntityAttribute == null || entityAttribute.equals(duplicateEntityAttribute)) {
246            var entityAttributeTypeName = entityAttribute.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
247            var entityListItemSequenceName = entityAttributeTypeName.equals(EntityAttributeTypes.LISTITEM.name())
248                    || entityAttributeTypeName.equals(EntityAttributeTypes.MULTIPLELISTITEM.name()) ?
249                    edit.getEntityListItemSequenceName() : null;
250
251            if(entityListItemSequenceName != null) {
252                var sequenceType = sequenceTypeLogic.getSequenceTypeByName(this, SequenceTypes.ENTITY_LIST_ITEM.name());
253
254                if(!hasExecutionErrors()) {
255                    entityListItemSequence = sequenceControl.getSequenceByName(sequenceType, entityListItemSequenceName);
256
257                    if(entityListItemSequence == null) {
258                        addExecutionError(ExecutionErrors.UnknownEntityListItemSequenceName.name(), entityListItemSequenceName);
259                    }
260                }
261            }
262
263            if(!hasExecutionErrors()) {
264                var unitOfMeasureKindName = edit.getUnitOfMeasureKindName();
265                var unitOfMeasureTypeName = edit.getUnitOfMeasureTypeName();
266                var parameterCount = (unitOfMeasureKindName == null ? 0 : 1) + (unitOfMeasureTypeName == null ? 0 : 1);
267                
268                if(parameterCount == 0 || parameterCount == 2) {
269                    if(parameterCount == 2) {
270                        unitOfMeasureType = unitOfMeasureTypeLogic.getUnitOfMeasureTypeByName(this, unitOfMeasureKindName, unitOfMeasureTypeName);
271                    }
272                } else {
273                    addExecutionError(ExecutionErrors.InvalidParameterCount.name());
274                }
275            }
276        } else {
277            addExecutionError(ExecutionErrors.DuplicateEntityAttributeName.name(), entityAttributeName);
278        }
279    }
280
281    @Override
282    public void doUpdate(EntityAttribute entityAttribute) {
283        var partyPK = getPartyPK();
284        var entityAttributeDetailValue = coreControl.getEntityAttributeDetailValueForUpdate(entityAttribute);
285        var entityAttributeDescription = coreControl.getEntityAttributeDescriptionForUpdate(entityAttribute, getPreferredLanguage());
286        var strCheckContentWebAddress = edit.getCheckContentWebAddress();
287        var checkContentWebAddress = strCheckContentWebAddress == null ? null : Boolean.valueOf(strCheckContentWebAddress);
288        var validationPattern = edit.getValidationPattern();
289        var strUpperRangeIntegerValue = edit.getUpperRangeIntegerValue();
290        var upperRangeIntegerValue = strUpperRangeIntegerValue == null ? null : Integer.valueOf(strUpperRangeIntegerValue);
291        var strUpperLimitIntegerValue = edit.getUpperLimitIntegerValue();
292        var upperLimitIntegerValue = strUpperLimitIntegerValue == null ? null : Integer.valueOf(strUpperLimitIntegerValue);
293        var strLowerLimitIntegerValue = edit.getLowerLimitIntegerValue();
294        var lowerLimitIntegerValue = strLowerLimitIntegerValue == null ? null : Integer.valueOf(strLowerLimitIntegerValue);
295        var strLowerRangeIntegerValue = edit.getLowerRangeIntegerValue();
296        var lowerRangeIntegerValue = strLowerRangeIntegerValue == null ? null : Integer.valueOf(strLowerRangeIntegerValue);
297        var strUpperRangeLongValue = edit.getUpperRangeLongValue();
298        var upperRangeLongValue = strUpperRangeLongValue == null ? null : Long.valueOf(strUpperRangeLongValue);
299        var strUpperLimitLongValue = edit.getUpperLimitLongValue();
300        var upperLimitLongValue = strUpperLimitLongValue == null ? null : Long.valueOf(strUpperLimitLongValue);
301        var strLowerLimitLongValue = edit.getLowerLimitLongValue();
302        var lowerLimitLongValue = strLowerLimitLongValue == null ? null : Long.valueOf(strLowerLimitLongValue);
303        var strLowerRangeLongValue = edit.getLowerRangeLongValue();
304        var lowerRangeLongValue = strLowerRangeLongValue == null ? null : Long.valueOf(strLowerRangeLongValue);
305        var description = edit.getDescription();
306
307        entityAttributeDetailValue.setEntityAttributeName(edit.getEntityAttributeName());
308        entityAttributeDetailValue.setTrackRevisions(Boolean.valueOf(edit.getTrackRevisions()));
309        entityAttributeDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
310
311        entityAttributeLogic.updateEntityAttributeFromValue(session, entityAttributeDetailValue, partyPK);
312
313        var entityAttributeTypeName = entityAttribute.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
314        var entityAttributeType = EntityAttributeTypes.valueOf(entityAttributeTypeName);
315
316        switch(entityAttributeType) {
317            case BLOB -> {
318                var entityAttributeBlobValue = coreControl.getEntityAttributeBlobValueForUpdate(entityAttribute);
319
320                entityAttributeBlobValue.setCheckContentWebAddress(checkContentWebAddress);
321                coreControl.updateEntityAttributeBlobFromValue(entityAttributeBlobValue, partyPK);
322            }
323            case STRING -> {
324                var entityAttributeString = coreControl.getEntityAttributeStringForUpdate(entityAttribute);
325
326                if(entityAttributeString == null && validationPattern != null) {
327                    coreControl.createEntityAttributeString(entityAttribute, validationPattern, partyPK);
328                } else if(entityAttributeString != null) {
329                    if(validationPattern == null) {
330                        coreControl.deleteEntityAttributeString(entityAttributeString, partyPK);
331                    } else {
332                        var entityAttributeStringValue = coreControl.getEntityAttributeStringValue(entityAttributeString);
333
334                        entityAttributeStringValue.setValidationPattern(validationPattern);
335                        coreControl.updateEntityAttributeStringFromValue(entityAttributeStringValue, partyPK);
336                    }
337                }
338            }
339            case INTEGER -> {
340                var entityAttributeInteger = coreControl.getEntityAttributeIntegerForUpdate(entityAttribute);
341                var entityAttributeNumeric = coreControl.getEntityAttributeNumericForUpdate(entityAttribute);
342
343                if(entityAttributeInteger == null && (upperRangeIntegerValue != null || upperLimitIntegerValue != null || lowerLimitIntegerValue != null || lowerRangeIntegerValue != null)) {
344                    coreControl.createEntityAttributeInteger(entityAttribute, upperRangeIntegerValue, upperLimitIntegerValue, lowerLimitIntegerValue, lowerRangeIntegerValue, partyPK);
345                } else if(entityAttributeInteger != null) {
346                    if(upperRangeIntegerValue == null && upperLimitIntegerValue == null && lowerLimitIntegerValue == null && lowerRangeIntegerValue == null) {
347                        coreControl.deleteEntityAttributeInteger(entityAttributeInteger, partyPK);
348                    } else {
349                        var entityAttributeIntegerValue = coreControl.getEntityAttributeIntegerValue(entityAttributeInteger);
350
351                        entityAttributeIntegerValue.setUpperRangeIntegerValue(upperRangeIntegerValue);
352                        entityAttributeIntegerValue.setUpperLimitIntegerValue(upperLimitIntegerValue);
353                        entityAttributeIntegerValue.setLowerLimitIntegerValue(lowerLimitIntegerValue);
354                        entityAttributeIntegerValue.setLowerRangeIntegerValue(lowerRangeIntegerValue);
355                        coreControl.updateEntityAttributeIntegerFromValue(entityAttributeIntegerValue, partyPK);
356                    }
357                }
358
359                if(entityAttributeNumeric == null && unitOfMeasureType != null) {
360                    coreControl.createEntityAttributeNumeric(entityAttribute, unitOfMeasureType, partyPK);
361                } else if(entityAttributeNumeric != null) {
362                    if(unitOfMeasureType == null) {
363                        coreControl.deleteEntityAttributeNumeric(entityAttributeNumeric, partyPK);
364                    } else {
365                        var entityAttributeNumericValue = coreControl.getEntityAttributeNumericValue(entityAttributeNumeric);
366
367                        entityAttributeNumericValue.setUnitOfMeasureTypePK(unitOfMeasureType.getPrimaryKey());
368                        coreControl.updateEntityAttributeNumericFromValue(entityAttributeNumericValue, partyPK);
369                    }
370                }
371            }
372            case LONG -> {
373                var entityAttributeLong = coreControl.getEntityAttributeLongForUpdate(entityAttribute);
374                var entityAttributeNumeric = coreControl.getEntityAttributeNumericForUpdate(entityAttribute);
375
376                if(entityAttributeLong == null && (upperRangeLongValue != null || upperLimitLongValue != null || lowerLimitLongValue != null || lowerRangeLongValue != null)) {
377                    coreControl.createEntityAttributeLong(entityAttribute, upperRangeLongValue, upperLimitLongValue, lowerLimitLongValue, lowerRangeLongValue, partyPK);
378                } else if(entityAttributeLong != null) {
379                    if(upperRangeLongValue == null && upperLimitLongValue == null && lowerLimitLongValue == null && lowerRangeLongValue == null) {
380                        coreControl.deleteEntityAttributeLong(entityAttributeLong, partyPK);
381                    } else {
382                        var entityAttributeLongValue = coreControl.getEntityAttributeLongValue(entityAttributeLong);
383
384                        entityAttributeLongValue.setUpperRangeLongValue(upperRangeLongValue);
385                        entityAttributeLongValue.setUpperLimitLongValue(upperLimitLongValue);
386                        entityAttributeLongValue.setLowerLimitLongValue(lowerLimitLongValue);
387                        entityAttributeLongValue.setLowerRangeLongValue(lowerRangeLongValue);
388                        coreControl.updateEntityAttributeLongFromValue(entityAttributeLongValue, partyPK);
389                    }
390                }
391
392                if(entityAttributeNumeric == null && unitOfMeasureType != null) {
393                    coreControl.createEntityAttributeNumeric(entityAttribute, unitOfMeasureType, partyPK);
394                } else if(entityAttributeNumeric != null) {
395                    if(unitOfMeasureType == null) {
396                        coreControl.deleteEntityAttributeNumeric(entityAttributeNumeric, partyPK);
397                    } else {
398                        var entityAttributeNumericValue = coreControl.getEntityAttributeNumericValue(entityAttributeNumeric);
399
400                        entityAttributeNumericValue.setUnitOfMeasureTypePK(unitOfMeasureType.getPrimaryKey());
401                        coreControl.updateEntityAttributeNumericFromValue(entityAttributeNumericValue, partyPK);
402                    }
403                }
404            }
405            case LISTITEM, MULTIPLELISTITEM -> {
406                var entityAttributeListItem = coreControl.getEntityAttributeListItemForUpdate(entityAttribute);
407
408                if(entityAttributeListItem == null && entityListItemSequence != null) {
409                    coreControl.createEntityAttributeListItem(entityAttribute, entityListItemSequence, partyPK);
410                } else if(entityAttributeListItem != null) {
411                    if(entityListItemSequence == null) {
412                        coreControl.deleteEntityAttributeListItem(entityAttributeListItem, partyPK);
413                    } else {
414                        var entityAttributeListItemValue = coreControl.getEntityAttributeListItemValue(entityAttributeListItem);
415
416                        entityAttributeListItemValue.setEntityListItemSequencePK(entityListItemSequence.getPrimaryKey());
417                        coreControl.updateEntityAttributeListItemFromValue(entityAttributeListItemValue, partyPK);
418                    }
419                }
420            }
421            default -> {
422            }
423        }
424        
425        if(entityAttributeDescription == null && description != null) {
426            coreControl.createEntityAttributeDescription(entityAttribute, getPreferredLanguage(), description, partyPK);
427        } else if(entityAttributeDescription != null) {
428            if(description == null) {
429                coreControl.deleteEntityAttributeDescription(entityAttributeDescription, partyPK);
430            } else {
431                var entityAttributeDescriptionValue = coreControl.getEntityAttributeDescriptionValue(entityAttributeDescription);
432
433                entityAttributeDescriptionValue.setDescription(description);
434                coreControl.updateEntityAttributeDescriptionFromValue(entityAttributeDescriptionValue, partyPK);
435            }
436        }
437    }
438    
439}