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