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