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.content.server.command; 018 019import com.echothree.control.user.content.common.edit.ContentCategoryEdit; 020import com.echothree.control.user.content.common.edit.ContentEditFactory; 021import com.echothree.control.user.content.common.form.EditContentCategoryForm; 022import com.echothree.control.user.content.common.result.ContentResultFactory; 023import com.echothree.control.user.content.common.result.EditContentCategoryResult; 024import com.echothree.control.user.content.common.spec.ContentCategorySpec; 025import com.echothree.model.control.content.common.ContentCategories; 026import com.echothree.model.control.content.server.control.ContentControl; 027import com.echothree.model.control.offer.server.control.OfferControl; 028import com.echothree.model.control.offer.server.control.OfferUseControl; 029import com.echothree.model.control.offer.server.control.SourceControl; 030import com.echothree.model.control.offer.server.control.UseControl; 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.control.selector.common.SelectorKinds; 036import com.echothree.model.control.selector.common.SelectorTypes; 037import com.echothree.model.control.selector.server.control.SelectorControl; 038import com.echothree.model.data.content.server.entity.ContentCatalog; 039import com.echothree.model.data.content.server.entity.ContentCategory; 040import com.echothree.model.data.offer.server.entity.OfferUse; 041import com.echothree.model.data.selector.server.entity.Selector; 042import com.echothree.model.data.user.common.pk.UserVisitPK; 043import com.echothree.util.common.command.EditMode; 044import com.echothree.util.common.message.ExecutionErrors; 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 EditContentCategoryCommand 057 extends BaseAbstractEditCommand<ContentCategorySpec, ContentCategoryEdit, EditContentCategoryResult, ContentCategory, ContentCategory> { 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.ContentCategory.name(), SecurityRoles.Edit.name()) 068 )) 069 )); 070 071 SPEC_FIELD_DEFINITIONS = List.of( 072 new FieldDefinition("ContentCollectionName", FieldType.ENTITY_NAME, true, null, null), 073 new FieldDefinition("ContentCatalogName", FieldType.ENTITY_NAME, true, null, null), 074 new FieldDefinition("ContentCategoryName", FieldType.ENTITY_NAME, true, null, null) 075 ); 076 077 EDIT_FIELD_DEFINITIONS = List.of( 078 new FieldDefinition("ContentCategoryName", FieldType.ENTITY_NAME, true, null, null), 079 new FieldDefinition("ParentContentCategoryName", FieldType.ENTITY_NAME, false, null, null), 080 new FieldDefinition("DefaultOfferName", FieldType.ENTITY_NAME, false, null, null), 081 new FieldDefinition("DefaultUseName", FieldType.ENTITY_NAME, false, null, null), 082 new FieldDefinition("DefaultSourceName", FieldType.ENTITY_NAME, false, null, null), 083 new FieldDefinition("ContentCategoryItemSelectorName", FieldType.ENTITY_NAME, false, null, null), 084 new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null), 085 new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null), 086 new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L) 087 ); 088 } 089 090 /** Creates a new instance of EditContentCategoryCommand */ 091 public EditContentCategoryCommand() { 092 super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 093 } 094 095 @Override 096 public EditContentCategoryResult getResult() { 097 return ContentResultFactory.getEditContentCategoryResult(); 098 } 099 100 @Override 101 public ContentCategoryEdit getEdit() { 102 return ContentEditFactory.getContentCategoryEdit(); 103 } 104 105 ContentCatalog contentCatalog = null; 106 107 @Override 108 public ContentCategory getEntity(EditContentCategoryResult result) { 109 var contentControl = Session.getModelController(ContentControl.class); 110 ContentCategory contentCategory = null; 111 var contentCollectionName = spec.getContentCollectionName(); 112 var contentCollection = contentControl.getContentCollectionByName(contentCollectionName); 113 114 if(contentCollection != null) { 115 var contentCatalogName = spec.getContentCatalogName(); 116 117 contentCatalog = contentControl.getContentCatalogByName(contentCollection, contentCatalogName); 118 119 if(contentCatalog != null) { 120 var contentCategoryName = spec.getContentCategoryName(); 121 122 if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) { 123 contentCategory = contentControl.getContentCategoryByName(contentCatalog, contentCategoryName); 124 } else { // EditMode.UPDATE 125 contentCategory = contentControl.getContentCategoryByNameForUpdate(contentCatalog, contentCategoryName); 126 } 127 128 if(contentCategory != null) { 129 result.setContentCategory(contentControl.getContentCategoryTransfer(getUserVisit(), contentCategory)); 130 } else { 131 addExecutionError(ExecutionErrors.UnknownContentCategoryName.name(), contentCategoryName); 132 } 133 } else { 134 addExecutionError(ExecutionErrors.UnknownContentCatalogName.name(), contentCatalogName); 135 } 136 } else { 137 addExecutionError(ExecutionErrors.UnknownContentCollectionName.name(), contentCollectionName); 138 } 139 140 return contentCategory; 141 } 142 143 @Override 144 public ContentCategory getLockEntity(ContentCategory contentCategory) { 145 return contentCategory; 146 } 147 148 @Override 149 public void fillInResult(EditContentCategoryResult result, ContentCategory contentCategory) { 150 var contentControl = Session.getModelController(ContentControl.class); 151 152 result.setContentCategory(contentControl.getContentCategoryTransfer(getUserVisit(), contentCategory)); 153 } 154 155 @Override 156 public void doLock(ContentCategoryEdit edit, ContentCategory contentCategory) { 157 var contentControl = Session.getModelController(ContentControl.class); 158 var sourceControl = Session.getModelController(SourceControl.class); 159 var contentCategoryDescription = contentControl.getContentCategoryDescription(contentCategory, getPreferredLanguage()); 160 var contentCategoryDetail = contentCategory.getLastDetail(); 161 var parentContentCategory = contentCategoryDetail.getParentContentCategory(); 162 var defaultOfferUse = contentCategoryDetail.getDefaultOfferUse(); 163 var defaultOfferUseDetail = defaultOfferUse == null ? null : defaultOfferUse.getLastDetail(); 164 var sources = defaultOfferUse == null ? null : sourceControl.getSourcesByOfferUse(defaultOfferUse); // List of Sources if there are any for the OfferUse 165 var defaultSourceName = sources == null ? null : sources.iterator().next().getLastDetail().getSourceName(); // From the List, the first available Source's SourceName 166 var contentCategoryItemSelector = contentCategoryDetail.getContentCategoryItemSelector(); 167 168 edit.setContentCategoryName(contentCategoryDetail.getContentCategoryName()); 169 edit.setParentContentCategoryName(parentContentCategory == null ? null : parentContentCategory.getLastDetail().getContentCategoryName()); 170 edit.setDefaultOfferName(defaultSourceName == null ? (defaultOfferUseDetail == null? null: defaultOfferUseDetail.getOffer().getLastDetail().getOfferName()) : null); 171 edit.setDefaultUseName(defaultSourceName == null ? (defaultOfferUseDetail == null ? null : defaultOfferUseDetail.getUse().getLastDetail().getUseName()) : null); 172 edit.setDefaultSourceName(defaultSourceName); 173 edit.setContentCategoryItemSelectorName(contentCategoryItemSelector == null? null: contentCategoryItemSelector.getLastDetail().getSelectorName()); 174 edit.setIsDefault(contentCategoryDetail.getIsDefault().toString()); 175 edit.setSortOrder(contentCategoryDetail.getSortOrder().toString()); 176 177 if(contentCategoryDescription != null) { 178 edit.setDescription(contentCategoryDescription.getDescription()); 179 } 180 } 181 182 ContentCategory parentContentCategory = null; 183 OfferUse defaultOfferUse = null; 184 Selector contentCategoryItemSelector = null; 185 186 @Override 187 public void canUpdate(ContentCategory contentCategory) { 188 var contentControl = Session.getModelController(ContentControl.class); 189 var contentCategoryName = edit.getContentCategoryName(); 190 var duplicateContentCategory = contentControl.getContentCategoryByName(contentCatalog, contentCategoryName); 191 192 if(duplicateContentCategory == null || contentCategory.equals(duplicateContentCategory)) { 193 var parentContentCategoryName = edit.getParentContentCategoryName(); 194 195 parentContentCategory = contentControl.getContentCategoryByName(contentCatalog, parentContentCategoryName == null ? 196 ContentCategories.ROOT.toString() : parentContentCategoryName); 197 198 if(parentContentCategory != null) { 199 if(contentControl.isParentContentCategorySafe(contentCategory, parentContentCategory)) { 200 var offerControl = Session.getModelController(OfferControl.class); 201 var defaultOfferName = edit.getDefaultOfferName(); 202 var defaultUseName = edit.getDefaultUseName(); 203 var defaultSourceName = edit.getDefaultSourceName(); 204 var invalidDefaultOfferOrSourceSpecification = false; 205 206 if(defaultOfferName != null && defaultUseName != null && defaultSourceName == null) { 207 var defaultOffer = offerControl.getOfferByName(defaultOfferName); 208 209 if(defaultOffer != null) { 210 var useControl = Session.getModelController(UseControl.class); 211 var defaultUse = useControl.getUseByName(defaultUseName); 212 213 if(defaultUse != null) { 214 var offerUseControl = Session.getModelController(OfferUseControl.class); 215 defaultOfferUse = offerUseControl.getOfferUse(defaultOffer, defaultUse); 216 217 if(defaultOfferUse == null) { 218 addExecutionError(ExecutionErrors.UnknownDefaultOfferUse.name()); 219 } 220 } else { 221 addExecutionError(ExecutionErrors.UnknownDefaultUseName.name(), defaultUseName); 222 } 223 } else { 224 addExecutionError(ExecutionErrors.UnknownDefaultOfferName.name(), defaultOfferName); 225 } 226 } else if(defaultOfferName == null && defaultUseName == null && defaultSourceName != null) { 227 var sourceControl = Session.getModelController(SourceControl.class); 228 var source = sourceControl.getSourceByName(defaultSourceName); 229 230 if(source != null) { 231 defaultOfferUse = source.getLastDetail().getOfferUse(); 232 } else { 233 addExecutionError(ExecutionErrors.UnknownDefaultSourceName.name(), defaultSourceName); 234 } 235 } else if(defaultOfferName == null && defaultUseName == null && defaultSourceName == null) { 236 // nothing 237 } else { 238 addExecutionError(ExecutionErrors.InvalidDefaultOfferOrSourceSpecification.name()); 239 invalidDefaultOfferOrSourceSpecification = true; 240 } 241 242 if(!invalidDefaultOfferOrSourceSpecification) { 243 var invalidOfferCompany = false; 244 245 if(defaultOfferUse != null) { 246 var partyControl = Session.getModelController(PartyControl.class); 247 var defaultOffer = defaultOfferUse.getLastDetail().getOffer(); 248 var defaultPartyDepartment = partyControl.getPartyDepartment(defaultOffer.getLastDetail().getDepartmentParty()); 249 var defaultPartyDivision = partyControl.getPartyDivision(defaultPartyDepartment.getDivisionParty()); 250 var defaultPartyCompany = partyControl.getPartyCompany(defaultPartyDivision.getCompanyParty()); 251 252 var catalogOffer = contentCatalog.getLastDetail().getDefaultOfferUse().getLastDetail().getOffer(); 253 var catalogPartyDepartment = partyControl.getPartyDepartment(catalogOffer.getLastDetail().getDepartmentParty()); 254 var catalogPartyDivision = partyControl.getPartyDivision(catalogPartyDepartment.getDivisionParty()); 255 var catalogPartyCompany = partyControl.getPartyCompany(catalogPartyDivision.getCompanyParty()); 256 257 if(!defaultPartyCompany.equals(catalogPartyCompany)) { 258 invalidOfferCompany = true; 259 } 260 } 261 262 if(!invalidOfferCompany) { 263 var contentCategoryItemSelectorName = edit.getContentCategoryItemSelectorName(); 264 265 if(contentCategoryItemSelectorName != null) { 266 var selectorControl = Session.getModelController(SelectorControl.class); 267 var selectorKind = selectorControl.getSelectorKindByName(SelectorKinds.ITEM.name()); 268 269 if(selectorKind != null) { 270 var selectorType = selectorControl.getSelectorTypeByName(selectorKind, SelectorTypes.CONTENT_CATEGORY.name()); 271 272 if(selectorType != null) { 273 contentCategoryItemSelector = selectorControl.getSelectorByName(selectorType, contentCategoryItemSelectorName); 274 } else { 275 addExecutionError(ExecutionErrors.UnknownSelectorTypeName.name(), SelectorTypes.CONTENT_CATEGORY.name()); 276 } 277 } else { 278 addExecutionError(ExecutionErrors.UnknownSelectorKindName.name(), SelectorKinds.ITEM.name()); 279 } 280 } 281 282 if(contentCategoryItemSelectorName != null && contentCategoryItemSelector == null) { 283 addExecutionError(ExecutionErrors.UnknownContentCategoryItemSelectorName.name(), contentCategoryItemSelectorName); 284 } 285 } else { 286 addExecutionError(ExecutionErrors.InvalidOfferCompany.name()); 287 } 288 } 289 } else { 290 addExecutionError(ExecutionErrors.InvalidParentContentCategory.name()); 291 } 292 } else { 293 addExecutionError(ExecutionErrors.UnknownParentContentCategoryName.name(), parentContentCategoryName); 294 } 295 } else { 296 addExecutionError(ExecutionErrors.DuplicateContentCategoryName.name(), contentCategoryName); 297 } 298 } 299 300 @Override 301 public void doUpdate(ContentCategory contentCategory) { 302 var contentControl = Session.getModelController(ContentControl.class); 303 var partyPK = getPartyPK(); 304 var contentCategoryDetailValue = contentControl.getContentCategoryDetailValueForUpdate(contentCategory); 305 var contentCategoryDescription = contentControl.getContentCategoryDescriptionForUpdate(contentCategory, getPreferredLanguage()); 306 var description = edit.getDescription(); 307 308 contentCategoryDetailValue.setContentCategoryName(edit.getContentCategoryName()); 309 contentCategoryDetailValue.setParentContentCategoryPK(parentContentCategory == null ? null : parentContentCategory.getPrimaryKey()); 310 contentCategoryDetailValue.setDefaultOfferUsePK(defaultOfferUse == null? null: defaultOfferUse.getPrimaryKey()); 311 contentCategoryDetailValue.setContentCategoryItemSelectorPK(contentCategoryItemSelector == null? null: contentCategoryItemSelector.getPrimaryKey()); 312 contentCategoryDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault())); 313 contentCategoryDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder())); 314 315 contentControl.updateContentCategoryFromValue(contentCategoryDetailValue, partyPK); 316 317 if(contentCategoryDescription == null && description != null) { 318 contentControl.createContentCategoryDescription(contentCategory, getPreferredLanguage(), description, partyPK); 319 } else if(contentCategoryDescription != null && description == null) { 320 contentControl.deleteContentCategoryDescription(contentCategoryDescription, partyPK); 321 } else if(contentCategoryDescription != null && description != null) { 322 var contentCategoryDescriptionValue = contentControl.getContentCategoryDescriptionValue(contentCategoryDescription); 323 324 contentCategoryDescriptionValue.setDescription(description); 325 contentControl.updateContentCategoryDescriptionFromValue(contentCategoryDescriptionValue, partyPK); 326 } 327 } 328 329}