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