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.util.server.persistence; 018 019import com.echothree.model.control.core.common.ComponentVendors; 020import com.echothree.model.control.core.common.EntityTypes; 021import com.echothree.model.control.security.common.SecurityRoleGroups; 022import com.echothree.model.control.security.common.SecurityRoles; 023import com.echothree.model.control.security.server.logic.SecurityRoleLogic; 024import com.echothree.model.control.sequence.common.SequenceTypes; 025import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic; 026import com.echothree.model.control.warehouse.server.control.WarehouseControl; 027import com.echothree.model.data.communication.common.pk.CommunicationEventPK; 028import com.echothree.model.data.communication.server.factory.CommunicationEventFactory; 029import com.echothree.model.data.contactlist.common.pk.PartyContactListPK; 030import com.echothree.model.data.contactlist.server.factory.PartyContactListFactory; 031import com.echothree.model.data.core.common.pk.ComponentVendorPK; 032import com.echothree.model.data.core.common.pk.EntityTypePK; 033import com.echothree.model.data.core.common.pk.MimeTypePK; 034import com.echothree.model.data.core.server.entity.EntityInstance; 035import com.echothree.model.data.core.server.factory.ComponentVendorFactory; 036import com.echothree.model.data.core.server.factory.EntityTypeFactory; 037import com.echothree.model.data.core.server.factory.MimeTypeFactory; 038import com.echothree.model.data.forum.common.pk.ForumGroupPK; 039import com.echothree.model.data.forum.common.pk.ForumMessagePK; 040import com.echothree.model.data.forum.common.pk.ForumPK; 041import com.echothree.model.data.forum.common.pk.ForumThreadPK; 042import com.echothree.model.data.forum.server.factory.ForumFactory; 043import com.echothree.model.data.forum.server.factory.ForumGroupFactory; 044import com.echothree.model.data.forum.server.factory.ForumMessageFactory; 045import com.echothree.model.data.forum.server.factory.ForumThreadFactory; 046import com.echothree.model.data.item.common.pk.ItemDescriptionPK; 047import com.echothree.model.data.item.common.pk.ItemPK; 048import com.echothree.model.data.item.server.factory.ItemDescriptionFactory; 049import com.echothree.model.data.item.server.factory.ItemFactory; 050import com.echothree.model.data.party.server.entity.Party; 051import com.echothree.model.data.subscription.common.pk.SubscriptionPK; 052import com.echothree.model.data.subscription.server.factory.SubscriptionFactory; 053import com.echothree.model.data.training.common.pk.PartyTrainingClassPK; 054import com.echothree.model.data.training.common.pk.TrainingClassPK; 055import com.echothree.model.data.training.server.factory.PartyTrainingClassFactory; 056import com.echothree.model.data.training.server.factory.TrainingClassFactory; 057import com.echothree.model.data.vendor.common.pk.VendorItemPK; 058import com.echothree.model.data.vendor.server.factory.VendorItemFactory; 059import com.echothree.model.data.warehouse.common.pk.LocationPK; 060import com.echothree.model.data.warehouse.server.factory.LocationFactory; 061import com.echothree.util.common.persistence.EntityNames; 062import com.echothree.util.common.persistence.Names; 063import com.echothree.util.common.persistence.Targets; 064import com.echothree.util.common.transfer.MapWrapper; 065import com.echothree.util.server.message.ExecutionErrorAccumulator; 066import com.echothree.util.server.persistence.translator.ComponentVendorTranslator; 067import com.echothree.util.server.persistence.translator.EntityInstanceAndNames; 068import com.echothree.util.server.persistence.translator.EntityInstanceTranslator; 069import com.echothree.util.server.persistence.translator.InvoiceNameTranslator; 070import com.echothree.util.server.persistence.translator.OrderNameTranslator; 071import com.echothree.util.server.persistence.translator.PartyNameTranslator; 072import com.echothree.util.server.persistence.translator.SequenceTypeTranslator; 073import java.util.Collections; 074import java.util.HashMap; 075import java.util.Map; 076 077public class EntityNamesUtils { 078 079 private EntityNamesUtils() { 080 super(); 081 } 082 083 private static class EntityNamesUtilsHolder { 084 static EntityNamesUtils instance = new EntityNamesUtils(); 085 } 086 087 public static EntityNamesUtils getInstance() { 088 return EntityNamesUtilsHolder.instance; 089 } 090 091 private final static Map<String, ComponentVendorTranslator> componentVendorTranslators = new HashMap<>(); 092 093 public static void addComponentVendorTranslator(String componentVendorName, ComponentVendorTranslator componentVendorTranslator) { 094 componentVendorTranslators.put(componentVendorName, componentVendorTranslator); 095 } 096 097 static { 098 Map<String, EntityInstanceTranslator> nameTranslators = new HashMap<>(16); 099 100 nameTranslators.put(EntityTypes.Invoice.name(), new InvoiceNameTranslator()); 101 nameTranslators.put(EntityTypes.Order.name(), new OrderNameTranslator()); 102 nameTranslators.put(EntityTypes.Party.name(), new PartyNameTranslator()); 103 104 nameTranslators.put(EntityTypes.Item.name(), (final EntityInstance entityInstance) -> { 105 var itemDetail = ItemFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 106 new ItemPK(entityInstance.getEntityUniqueId())).getLastDetail(); 107 var names = new MapWrapper<String>(1); 108 109 names.put(Names.ItemName.name(), itemDetail.getItemName()); 110 111 return new EntityNames(Targets.Item.name(), names); 112 }); 113 114 nameTranslators.put(EntityTypes.ItemDescription.name(), (final EntityInstance entityInstance) -> { 115 var itemDescriptionDetail = ItemDescriptionFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 116 new ItemDescriptionPK(entityInstance.getEntityUniqueId())).getLastDetail(); 117 var names = new MapWrapper<String>(3); 118 119 names.put(Names.ItemDescriptionTypeName.name(), itemDescriptionDetail.getItemDescriptionType().getLastDetail().getItemDescriptionTypeName()); 120 names.put(Names.ItemName.name(), itemDescriptionDetail.getItem().getLastDetail().getItemName()); 121 names.put(Names.LanguageIsoName.name(), itemDescriptionDetail.getLanguage().getLanguageIsoName()); 122 123 return new EntityNames(Targets.ItemDescription.name(), names); 124 }); 125 126 nameTranslators.put(EntityTypes.ForumGroup.name(), (final EntityInstance entityInstance) -> { 127 var forumGroupDetail = ForumGroupFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 128 new ForumGroupPK(entityInstance.getEntityUniqueId())).getLastDetail(); 129 var names = new MapWrapper<String>(1); 130 131 names.put(Names.ForumGroupName.name(), forumGroupDetail.getForumGroupName()); 132 133 return new EntityNames(Targets.ForumGroup.name(), names); 134 }); 135 136 nameTranslators.put(EntityTypes.Forum.name(), (final EntityInstance entityInstance) -> { 137 var forumDetail = ForumFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 138 new ForumPK(entityInstance.getEntityUniqueId())).getLastDetail(); 139 var names = new MapWrapper<String>(1); 140 141 names.put(Names.ForumName.name(), forumDetail.getForumName()); 142 143 return new EntityNames(Targets.Forum.name(), names); 144 }); 145 146 nameTranslators.put(EntityTypes.ForumMessage.name(), (final EntityInstance entityInstance) -> { 147 var forumMessageDetail = ForumMessageFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 148 new ForumMessagePK(entityInstance.getEntityUniqueId())).getLastDetail(); 149 var names = new MapWrapper<String>(1); 150 151 names.put(Names.ForumMessageName.name(), forumMessageDetail.getForumMessageName()); 152 153 return new EntityNames(Targets.ForumMessage.name(), names); 154 }); 155 156 nameTranslators.put(EntityTypes.ForumThread.name(), (final EntityInstance entityInstance) -> { 157 var forumThreadDetail = ForumThreadFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 158 new ForumThreadPK(entityInstance.getEntityUniqueId())).getLastDetail(); 159 var names = new MapWrapper<String>(1); 160 161 names.put(Names.ForumThreadName.name(), forumThreadDetail.getForumThreadName()); 162 163 return new EntityNames(Targets.ForumThread.name(), names); 164 }); 165 166 nameTranslators.put(EntityTypes.TrainingClass.name(), (final EntityInstance entityInstance) -> { 167 var trainingClassDetail = TrainingClassFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 168 new TrainingClassPK(entityInstance.getEntityUniqueId())).getLastDetail(); 169 var names = new MapWrapper<String>(1); 170 171 names.put(Names.TrainingClassName.name(), trainingClassDetail.getTrainingClassName()); 172 173 return new EntityNames(Targets.TrainingClass.name(), names); 174 }); 175 176 nameTranslators.put(EntityTypes.PartyTrainingClass.name(), (final EntityInstance entityInstance) -> { 177 var partyTrainingClassDetail = PartyTrainingClassFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 178 new PartyTrainingClassPK(entityInstance.getEntityUniqueId())).getLastDetail(); 179 var names = new MapWrapper<String>(1); 180 181 names.put(Names.PartyTrainingClassName.name(), partyTrainingClassDetail.getPartyTrainingClassName()); 182 183 return new EntityNames(Targets.PartyTrainingClass.name(), names); 184 }); 185 186 nameTranslators.put(EntityTypes.CommunicationEvent.name(), (final EntityInstance entityInstance) -> { 187 var communicationEventDetail = CommunicationEventFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 188 new CommunicationEventPK(entityInstance.getEntityUniqueId())).getLastDetail(); 189 var names = new MapWrapper<String>(1); 190 191 names.put(Names.CommunicationEventName.name(), communicationEventDetail.getCommunicationEventName()); 192 193 return new EntityNames(Targets.CommunicationEvent.name(), names); 194 }); 195 196 nameTranslators.put(EntityTypes.VendorItem.name(), (final EntityInstance entityInstance) -> { 197 var vendorItemDetail = VendorItemFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 198 new VendorItemPK(entityInstance.getEntityUniqueId())).getLastDetail(); 199 var names = new MapWrapper<String>(2); 200 201 names.put(Names.VendorItemName.name(), vendorItemDetail.getVendorItemName()); 202 names.put(Names.PartyName.name(), vendorItemDetail.getVendorParty().getLastDetail().getPartyName()); 203 204 return new EntityNames(Targets.VendorItem.name(), names); 205 }); 206 207 nameTranslators.put(EntityTypes.PartyContactList.name(), (final EntityInstance entityInstance) -> { 208 var partyContactListDetail = PartyContactListFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 209 new PartyContactListPK(entityInstance.getEntityUniqueId())).getLastDetail(); 210 var names = new MapWrapper<String>(2); 211 212 names.put(Names.PartyName.name(), partyContactListDetail.getParty().getLastDetail().getPartyName()); 213 names.put(Names.ContactListName.name(), partyContactListDetail.getContactList().getLastDetail().getContactListName()); 214 215 return new EntityNames(Targets.PartyContactList.name(), names); 216 }); 217 218 nameTranslators.put(EntityTypes.Subscription.name(), (final EntityInstance entityInstance) -> { 219 var subscription = SubscriptionFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 220 new SubscriptionPK(entityInstance.getEntityUniqueId())); 221 var names = new MapWrapper<String>(1); 222 223 names.put(Names.SubscriptionName.name(), subscription.getLastDetail().getSubscriptionName()); 224 225 return new EntityNames(Targets.Subscription.name(), names); 226 }); 227 228 nameTranslators.put(EntityTypes.MimeType.name(), (final EntityInstance entityInstance) -> { 229 var mimeType = MimeTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 230 new MimeTypePK(entityInstance.getEntityUniqueId())); 231 var names = new MapWrapper<String>(1); 232 233 names.put(Names.MimeTypeName.name(), mimeType.getLastDetail().getMimeTypeName()); 234 235 return new EntityNames(Targets.MimeType.name(), names); 236 }); 237 238 nameTranslators.put(EntityTypes.Location.name(), (final EntityInstance entityInstance) -> { 239 var warehouseControl = Session.getModelController(WarehouseControl.class); 240 var location = LocationFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 241 new LocationPK(entityInstance.getEntityUniqueId())); 242 var names = new MapWrapper<String>(2); 243 var locationDetail = location.getLastDetail(); 244 245 names.put(Names.WarehouseName.name(), warehouseControl.getWarehouse(locationDetail.getWarehouseParty()).getWarehouseName()); 246 names.put(Names.LocationName.name(), locationDetail.getLocationName()); 247 248 return new EntityNames(Targets.Location.name(), names); 249 }); 250 251 nameTranslators.put(EntityTypes.ComponentVendor.name(), (final EntityInstance entityInstance) -> { 252 var componentVendor = ComponentVendorFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 253 new ComponentVendorPK(entityInstance.getEntityUniqueId())); 254 var names = new MapWrapper<String>(1); 255 256 names.put(Names.ComponentVendorName.name(), componentVendor.getLastDetail().getComponentVendorName()); 257 258 return new EntityNames(Targets.ComponentVendor.name(), names); 259 }); 260 261 nameTranslators.put(EntityTypes.EntityType.name(), (final EntityInstance entityInstance) -> { 262 var entityType = EntityTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, 263 new EntityTypePK(entityInstance.getEntityUniqueId())); 264 var names = new MapWrapper<String>(2); 265 var entityTypeDetail = entityType.getLastDetail(); 266 267 names.put(Names.ComponentVendorName.name(), entityTypeDetail.getComponentVendor().getLastDetail().getComponentVendorName()); 268 names.put(Names.EntityTypeName.name(), entityTypeDetail.getEntityTypeName()); 269 270 return new EntityNames(Targets.EntityType.name(), names); 271 }); 272 273 nameTranslators = Collections.unmodifiableMap(nameTranslators); 274 275 addComponentVendorTranslator(ComponentVendors.ECHO_THREE.name(), new ComponentVendorTranslator(nameTranslators)); 276 } 277 278 // Entry point from the Identify UC. Permissions have already been checked at this point. 279 public EntityInstanceAndNames getEntityNames(final EntityInstance entityInstance) { 280 EntityNames result = null; 281 var entityType = entityInstance.getEntityType(); 282 var componentVendor = entityType.getLastDetail().getComponentVendor(); 283 var componentVendorName = componentVendor.getLastDetail().getComponentVendorName(); 284 285 var componentVendorTranslator = componentVendorTranslators.get(componentVendorName); 286 287 if(componentVendorTranslator != null) { 288 var nameTranslator = componentVendorTranslator.getNameTranslators().get(entityType.getLastDetail().getEntityTypeName()); 289 290 if(nameTranslator != null) { 291 result = nameTranslator.getNames(entityInstance); 292 } 293 } 294 295 return result == null ? null : new EntityInstanceAndNames(entityInstance, result); 296 } 297 298 private final static Map<String, SequenceTypeTranslator> sequenceTypeTranslators; 299 300 private final static InvoiceNameTranslator INVOICE_NAME_TRANSLATOR = new InvoiceNameTranslator(); 301 private final static OrderNameTranslator ORDER_NAME_TRANSLATOR = new OrderNameTranslator(); 302 private final static PartyNameTranslator PARTY_NAME_TRANSLATOR = new PartyNameTranslator(); 303 304 static { 305 var sequenceTypeTranslatorsMap = new HashMap<String, SequenceTypeTranslator>(7); 306 307 sequenceTypeTranslatorsMap.put(SequenceTypes.PURCHASE_INVOICE.name(), INVOICE_NAME_TRANSLATOR); 308 sequenceTypeTranslatorsMap.put(SequenceTypes.SALES_INVOICE.name(), INVOICE_NAME_TRANSLATOR); 309 sequenceTypeTranslatorsMap.put(SequenceTypes.PURCHASE_ORDER.name(), ORDER_NAME_TRANSLATOR); 310 sequenceTypeTranslatorsMap.put(SequenceTypes.SALES_ORDER.name(), ORDER_NAME_TRANSLATOR); 311 sequenceTypeTranslatorsMap.put(SequenceTypes.WISHLIST.name(), ORDER_NAME_TRANSLATOR); 312 sequenceTypeTranslatorsMap.put(SequenceTypes.CUSTOMER.name(), PARTY_NAME_TRANSLATOR); 313 sequenceTypeTranslatorsMap.put(SequenceTypes.EMPLOYEE.name(), PARTY_NAME_TRANSLATOR); 314 315 sequenceTypeTranslators = Collections.unmodifiableMap(sequenceTypeTranslatorsMap); 316 } 317 318 private EntityInstanceAndNames getEntityNames(final String sequenceTypeName, final String value, 319 final boolean includeEntityInstance) { 320 EntityInstanceAndNames result = null; 321 var sequenceTypeTranslator = sequenceTypeTranslators.get(sequenceTypeName); 322 323 if(sequenceTypeTranslator != null) { 324 result = sequenceTypeTranslator.getNames(sequenceTypeName, value, includeEntityInstance); 325 } 326 327 return result; 328 } 329 330 // Entry point from the Identify UC. Permissions have NOT been checked at this point. 331 public EntityInstanceAndNames getEntityNames(final ExecutionErrorAccumulator eea, final Party requestingParty, 332 final String value, final boolean includeEntityInstance) { 333 EntityInstanceAndNames result = null; 334 var sequenceType = SequenceGeneratorLogic.getInstance().identifySequenceType(value); 335 336 if(sequenceType != null) { 337 var sequenceTypeName = sequenceType.getLastDetail().getSequenceTypeName(); 338 var hasAccess = false; 339 340 if(sequenceTypeName.equals(SequenceTypes.PURCHASE_INVOICE.name()) 341 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 342 SecurityRoleGroups.PurchaseInvoice.name(), SecurityRoles.Search.name())) { 343 hasAccess = true; 344 } else if(sequenceTypeName.equals(SequenceTypes.SALES_INVOICE.name()) 345 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 346 SecurityRoleGroups.SalesOrder.name(), SecurityRoles.Search.name())) { 347 hasAccess = true; 348 } else if(sequenceTypeName.equals(SequenceTypes.PURCHASE_ORDER.name()) 349 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 350 SecurityRoleGroups.PurchaseOrder.name(), SecurityRoles.Search.name())) { 351 hasAccess = true; 352 } else if(sequenceTypeName.equals(SequenceTypes.SALES_ORDER.name()) 353 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 354 SecurityRoleGroups.SalesOrder.name(), SecurityRoles.Search.name())) { 355 hasAccess = true; 356 } else if(sequenceTypeName.equals(SequenceTypes.WISHLIST.name()) 357 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 358 SecurityRoleGroups.Wishlist.name(), SecurityRoles.Search.name())) { 359 hasAccess = true; 360 } else if(sequenceTypeName.equals(SequenceTypes.CUSTOMER.name()) 361 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 362 SecurityRoleGroups.Customer.name(), SecurityRoles.Search.name())) { 363 hasAccess = true; 364 } else if(sequenceTypeName.equals(SequenceTypes.EMPLOYEE.name()) 365 && SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(eea, requestingParty, 366 SecurityRoleGroups.Employee.name(), SecurityRoles.Search.name())) { 367 hasAccess = true; 368 } 369 370 result = hasAccess ? getEntityNames(sequenceTypeName, value, includeEntityInstance) : null; 371 } 372 373 return result; 374 } 375 376}