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.item.server.command; 018 019import com.echothree.control.user.item.common.edit.ItemDescriptionEdit; 020import com.echothree.control.user.item.common.edit.ItemEditFactory; 021import com.echothree.control.user.item.common.form.EditItemDescriptionForm; 022import com.echothree.control.user.item.common.result.EditItemDescriptionResult; 023import com.echothree.control.user.item.common.result.ItemResultFactory; 024import com.echothree.control.user.item.common.spec.ItemDescriptionSpec; 025import com.echothree.model.control.core.common.EntityAttributeTypes; 026import com.echothree.model.control.core.common.MimeTypeUsageTypes; 027import com.echothree.model.control.core.server.control.MimeTypeControl; 028import com.echothree.model.control.item.server.control.ItemControl; 029import com.echothree.model.control.item.server.logic.ItemDescriptionLogic; 030import com.echothree.model.control.item.server.logic.ItemDescriptionLogic.ImageDimensions; 031import com.echothree.model.control.party.common.PartyTypes; 032import com.echothree.model.control.party.server.control.PartyControl; 033import com.echothree.model.control.security.common.SecurityRoleGroups; 034import com.echothree.model.control.security.common.SecurityRoles; 035import com.echothree.model.data.core.server.entity.MimeType; 036import com.echothree.model.data.item.server.entity.Item; 037import com.echothree.model.data.item.server.entity.ItemDescription; 038import com.echothree.model.data.item.server.entity.ItemDescriptionType; 039import com.echothree.model.data.item.server.entity.ItemImageType; 040import com.echothree.model.data.user.common.pk.UserVisitPK; 041import com.echothree.util.common.command.EditMode; 042import com.echothree.util.common.message.ExecutionErrors; 043import com.echothree.util.common.persistence.BasePK; 044import com.echothree.util.common.persistence.type.ByteArray; 045import com.echothree.util.common.validation.FieldDefinition; 046import com.echothree.util.common.validation.FieldType; 047import com.echothree.util.server.control.BaseAbstractEditCommand; 048import com.echothree.util.server.control.CommandSecurityDefinition; 049import com.echothree.util.server.control.PartyTypeDefinition; 050import com.echothree.util.server.control.SecurityRoleDefinition; 051import com.echothree.util.server.persistence.Session; 052import java.util.List; 053import javax.enterprise.context.Dependent; 054 055@Dependent 056public class EditItemDescriptionCommand 057 extends BaseAbstractEditCommand<ItemDescriptionSpec, ItemDescriptionEdit, EditItemDescriptionResult, ItemDescription, ItemDescription> { 058 059 private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION; 060 private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS; 061 private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS; 062 063 static { 064 COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of( 065 new PartyTypeDefinition(PartyTypes.UTILITY.name(), null), 066 new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of( 067 new SecurityRoleDefinition(SecurityRoleGroups.ItemDescription.name(), SecurityRoles.Edit.name()) 068 )) 069 )); 070 071 SPEC_FIELD_DEFINITIONS = List.of( 072 new FieldDefinition("ItemName", FieldType.ENTITY_NAME, true, null, null), 073 new FieldDefinition("ItemDescriptionTypeName", FieldType.ENTITY_NAME, true, null, null), 074 new FieldDefinition("LanguageIsoName", FieldType.ENTITY_NAME, true, null, null) 075 ); 076 077 EDIT_FIELD_DEFINITIONS = List.of( 078 new FieldDefinition("MimeTypeName", FieldType.MIME_TYPE, false, null, null), 079 new FieldDefinition("ItemImageTypeName", FieldType.ENTITY_NAME, false, null, null), 080 new FieldDefinition("ClobDescription", FieldType.STRING, false, 1L, null), 081 new FieldDefinition("StringDescription", FieldType.STRING, false, 1L, 512L) 082 ); 083 } 084 085 /** Creates a new instance of EditItemDescriptionCommand */ 086 public EditItemDescriptionCommand() { 087 super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 088 } 089 090 @Override 091 public EditItemDescriptionResult getResult() { 092 return ItemResultFactory.getEditItemDescriptionResult(); 093 } 094 095 @Override 096 public ItemDescriptionEdit getEdit() { 097 return ItemEditFactory.getItemDescriptionEdit(); 098 } 099 100 ItemDescriptionType itemDescriptionType; 101 Item item; 102 103 @Override 104 public ItemDescription getEntity(EditItemDescriptionResult result) { 105 var itemControl = Session.getModelController(ItemControl.class); 106 ItemDescription itemDescription = null; 107 var itemDescriptionTypeName = spec.getItemDescriptionTypeName(); 108 109 itemDescriptionType = itemControl.getItemDescriptionTypeByName(itemDescriptionTypeName); 110 111 if(itemDescriptionType != null) { 112 var itemName = spec.getItemName(); 113 114 item = itemControl.getItemByName(itemName); 115 116 if(item != null) { 117 var partyControl = Session.getModelController(PartyControl.class); 118 var languageIsoName = spec.getLanguageIsoName(); 119 var language = partyControl.getLanguageByIsoName(languageIsoName); 120 121 if(language != null) { 122 if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) { 123 itemDescription = itemControl.getItemDescription(itemDescriptionType, item, language); 124 } else { // EditMode.UPDATE 125 itemDescription = itemControl.getItemDescriptionForUpdate(itemDescriptionType, item, language); 126 } 127 128 if(itemDescription == null) { 129 addExecutionError(ExecutionErrors.UnknownItemDescription.name(), itemDescriptionTypeName, itemName, languageIsoName); 130 } 131 } else { 132 addExecutionError(ExecutionErrors.UnknownLanguageIsoName.name(), languageIsoName); 133 } 134 } else { 135 addExecutionError(ExecutionErrors.UnknownItemName.name(), itemName); 136 } 137 } else { 138 addExecutionError(ExecutionErrors.UnknownItemDescriptionTypeName.name(), itemDescriptionTypeName); 139 } 140 141 return itemDescription; 142 } 143 144 @Override 145 public ItemDescription getLockEntity(ItemDescription itemDescription) { 146 return itemDescription; 147 } 148 149 @Override 150 public void fillInResult(EditItemDescriptionResult result, ItemDescription itemDescription) { 151 var itemControl = Session.getModelController(ItemControl.class); 152 153 result.setItemDescription(itemControl.getItemDescriptionTransfer(getUserVisit(), itemDescription)); 154 } 155 156 MimeType mimeType; 157 158 @Override 159 public void doLock(ItemDescriptionEdit edit, ItemDescription itemDescription) { 160 var itemControl = Session.getModelController(ItemControl.class); 161 162 mimeType = itemDescription.getLastDetail().getMimeType(); 163 164 edit.setMimeTypeName(mimeType == null? null: mimeType.getLastDetail().getMimeTypeName()); 165 166 if(mimeType == null) { 167 var itemStringDescription = itemControl.getItemStringDescription(itemDescription); 168 169 if(itemStringDescription != null) { 170 edit.setStringDescription(itemStringDescription.getStringDescription()); 171 } 172 } else { 173 var entityAttributeTypeName = mimeType.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName(); 174 175 // EntityAttributeTypes.BLOB.name() does not return anything in edit 176 if(entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) { 177 var itemClobDescription = itemControl.getItemClobDescription(itemDescription); 178 179 if(itemClobDescription != null) { 180 edit.setClobDescription(itemClobDescription.getClobDescription()); 181 } 182 } 183 } 184 } 185 186 ItemImageType itemImageType; 187 ImageDimensions imageDimensions; 188 189 @Override 190 public void canUpdate(ItemDescription itemDescription) { 191 var mimeTypeName = edit.getMimeTypeName(); 192 193 if(mimeTypeName == null) { 194 if(itemDescriptionType.getLastDetail().getMimeTypeUsageType() == null) { 195 var stringDescription = edit.getStringDescription(); 196 197 if(stringDescription == null) { 198 addExecutionError(ExecutionErrors.MissingStringDescription.name()); 199 } 200 } else { 201 // No mimeTypeName was supplied, but yet we required a MimeTypeUsageType 202 addExecutionError(ExecutionErrors.InvalidMimeType.name()); 203 } 204 } else { 205 var mimeTypeControl = Session.getModelController(MimeTypeControl.class); 206 207 mimeType = mimeTypeControl.getMimeTypeByName(mimeTypeName); 208 209 if(mimeType != null) { 210 var mimeTypeUsageType = itemDescriptionType.getLastDetail().getMimeTypeUsageType(); 211 212 if(mimeTypeUsageType != null) { 213 var mimeTypeUsage = mimeTypeControl.getMimeTypeUsage(mimeType, mimeTypeUsageType); 214 215 if(mimeTypeUsage != null) { 216 var mimeTypeDetail = mimeType.getLastDetail(); 217 var entityAttributeType = mimeTypeDetail.getEntityAttributeType(); 218 var entityAttributeTypeName = entityAttributeType.getEntityAttributeTypeName(); 219 220 if(entityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) { 221 var blobDescription = edit.getBlobDescription(); 222 223 if(blobDescription == null) { 224 addExecutionError(ExecutionErrors.MissingBlobDescription.name()); 225 } else { 226 var mimeTypeUsageTypeName = mimeTypeUsageType.getMimeTypeUsageTypeName(); 227 228 if(mimeTypeUsageTypeName.equals(MimeTypeUsageTypes.IMAGE.name())) { 229 var itemImageTypeName = edit.getItemImageTypeName(); 230 231 if(itemImageTypeName != null) { 232 var itemControl = Session.getModelController(ItemControl.class); 233 234 itemImageType = itemControl.getItemImageTypeByName(itemImageTypeName); 235 236 if(itemImageType != null) { 237 imageDimensions = ItemDescriptionLogic.getInstance().getImageDimensions(mimeTypeDetail.getMimeTypeName(), blobDescription); 238 239 if(imageDimensions == null) { 240 addExecutionError(ExecutionErrors.InvalidImage.name()); 241 } else { 242 var itemImageDescriptionType = itemControl.getItemImageDescriptionType(itemDescriptionType); 243 244 if(itemImageDescriptionType != null) { 245 var minimumHeight = itemImageDescriptionType.getMinimumHeight(); 246 var minimumWidth = itemImageDescriptionType.getMinimumWidth(); 247 var maximumHeight = itemImageDescriptionType.getMaximumHeight(); 248 var maximumWidth = itemImageDescriptionType.getMaximumWidth(); 249 var imageHeight = imageDimensions.getHeight(); 250 var imageWidth = imageDimensions.getWidth(); 251 252 if(minimumHeight != null && imageHeight < minimumHeight) { 253 addExecutionError(ExecutionErrors.ImageHeightLessThanMinimum.name(), imageHeight.toString(), minimumHeight.toString()); 254 } 255 256 if(minimumWidth != null && imageWidth < minimumWidth) { 257 addExecutionError(ExecutionErrors.ImageWidthLessThanMinimum.name(), imageWidth.toString(), minimumWidth.toString()); 258 } 259 260 if(maximumHeight != null && imageHeight > maximumHeight) { 261 addExecutionError(ExecutionErrors.ImageHeightGreaterThanMaximum.name(), imageHeight.toString(), maximumHeight.toString()); 262 } 263 264 if(maximumWidth != null && imageWidth > maximumWidth) { 265 addExecutionError(ExecutionErrors.ImageWidthGreaterThanMaximum.name(), imageWidth.toString(), maximumWidth.toString()); 266 } 267 } 268 } 269 } else { 270 addExecutionError(ExecutionErrors.UnknownItemImageTypeName.name(), itemImageTypeName); 271 } 272 } else { 273 addExecutionError(ExecutionErrors.MissingRequiredItemImageTypeName.name()); 274 } 275 } 276 } 277 } else if(entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) { 278 var clobDescription = edit.getClobDescription(); 279 280 if(clobDescription == null) { 281 addExecutionError(ExecutionErrors.MissingClobDescription.name()); 282 } 283 } else { 284 addExecutionError(ExecutionErrors.UnknownEntityAttributeTypeName.name(), 285 entityAttributeTypeName); 286 } 287 } else { 288 addExecutionError(ExecutionErrors.UnknownMimeTypeUsage.name()); 289 } 290 } else { 291 // mimeTypeName was supplied, and there shouldn't be one 292 addExecutionError(ExecutionErrors.InvalidMimeType.name()); 293 } 294 } else { 295 addExecutionError(ExecutionErrors.UnknownMimeTypeName.name(), mimeTypeName); 296 } 297 } 298 } 299 300 @Override 301 public void doUpdate(ItemDescription itemDescription) { 302 var itemControl = Session.getModelController(ItemControl.class); 303 var partyPK = getPartyPK(); 304 305 if(mimeType == null) { 306 var stringDescription = edit.getStringDescription(); 307 308 updateItemDescription(itemControl, item, null, partyPK, itemDescription, null, null, stringDescription); 309 } else { 310 var entityAttributeType = mimeType.getLastDetail().getEntityAttributeType(); 311 var entityAttributeTypeName = entityAttributeType.getEntityAttributeTypeName(); 312 313 if(entityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) { 314 var blobDescription = edit.getBlobDescription(); 315 316 updateItemDescription(itemControl, item, mimeType, partyPK, itemDescription, blobDescription, null, null); 317 } else { 318 if(entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) { 319 var clobDescription = edit.getClobDescription(); 320 321 updateItemDescription(itemControl, item, mimeType, partyPK, itemDescription, null, clobDescription, null); 322 } 323 } 324 } 325 } 326 327 protected void updateItemDescription(ItemControl itemControl, Item item, MimeType mimeType, BasePK updatedBy, 328 ItemDescription itemDescription, ByteArray blobDescription, String clobDescription, String stringDescription) { 329 var itemDescriptionDetailValue = itemControl.getItemDescriptionDetailValueForUpdate(itemDescription); 330 331 itemDescriptionDetailValue.setMimeTypePK(mimeType == null? null: mimeType.getPrimaryKey()); 332 itemControl.updateItemDescriptionFromValue(itemDescriptionDetailValue, updatedBy); 333 334 var itemBlobDescription = itemControl.getItemBlobDescriptionForUpdate(itemDescription); 335 336 if(itemBlobDescription != null) { 337 if(blobDescription == null) { 338 itemControl.deleteItemBlobDescription(itemBlobDescription, updatedBy); 339 itemControl.deleteItemImageDescriptionByItemDescription(itemDescription, updatedBy); 340 } else { 341 var itemBlobDescriptionValue = itemControl.getItemBlobDescriptionValue(itemBlobDescription); 342 var itemImageDescriptionValue = itemControl.getItemImageDescriptionValueForUpdate(itemDescription); 343 344 itemBlobDescriptionValue.setBlobDescription(blobDescription); 345 itemControl.updateItemBlobDescriptionFromValue(itemBlobDescriptionValue, updatedBy); 346 347 if(imageDimensions != null) { 348 itemImageDescriptionValue.setHeight(imageDimensions.getHeight()); 349 itemImageDescriptionValue.setWidth(imageDimensions.getWidth()); 350 itemImageDescriptionValue.setScaledFromParent(false); 351 352 itemControl.updateItemImageDescriptionFromValue(itemImageDescriptionValue, updatedBy); 353 } 354 355 if(itemBlobDescriptionValue.hasBeenModified()) { 356 ItemDescriptionLogic.getInstance().deleteItemImageDescriptionChildren(itemDescription, updatedBy); 357 } 358 } 359 } else if(blobDescription != null) { 360 itemControl.createItemBlobDescription(itemDescription, blobDescription, updatedBy); 361 362 if(imageDimensions != null) { 363 itemControl.createItemImageDescription(itemDescription, itemImageType, imageDimensions.getHeight(), imageDimensions.getWidth(), false, 364 updatedBy); 365 } 366 367 ItemDescriptionLogic.getInstance().deleteItemImageDescriptionChildren(itemDescription, updatedBy); 368 } 369 370 var itemClobDescription = itemControl.getItemClobDescriptionForUpdate(itemDescription); 371 372 if(itemClobDescription != null) { 373 if(clobDescription == null) { 374 itemControl.deleteItemClobDescription(itemClobDescription, updatedBy); 375 } else { 376 var itemClobDescriptionValue = itemControl.getItemClobDescriptionValue(itemClobDescription); 377 378 itemClobDescriptionValue.setClobDescription(clobDescription); 379 itemControl.updateItemClobDescriptionFromValue(itemClobDescriptionValue, updatedBy); 380 } 381 } else if(clobDescription != null) { 382 itemControl.createItemClobDescription(itemDescription, clobDescription, updatedBy); 383 } 384 385 var itemStringDescription = itemControl.getItemStringDescriptionForUpdate(itemDescription); 386 387 if(itemStringDescription != null) { 388 if(stringDescription == null) { 389 itemControl.deleteItemStringDescription(itemStringDescription, updatedBy); 390 } else { 391 var itemStringDescriptionValue = itemControl.getItemStringDescriptionValue(itemStringDescription); 392 393 itemStringDescriptionValue.setStringDescription(stringDescription); 394 itemControl.updateItemStringDescriptionFromValue(itemStringDescriptionValue, updatedBy); 395 } 396 } else if(stringDescription != null) { 397 itemControl.createItemStringDescription(itemDescription, stringDescription, updatedBy); 398 } 399 } 400 401}