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.control.user.search.server.command;
018
019import com.echothree.control.user.search.common.form.IdentifyForm;
020import com.echothree.control.user.search.common.result.SearchResultFactory;
021import com.echothree.model.control.core.common.CoreOptions;
022import com.echothree.model.control.core.common.CoreProperties;
023import com.echothree.model.control.core.common.transfer.ComponentVendorTransfer;
024import com.echothree.model.control.core.common.transfer.EntityInstanceTransfer;
025import com.echothree.model.control.core.common.transfer.EntityTypeTransfer;
026import com.echothree.model.control.core.server.control.EntityInstanceControl;
027import com.echothree.model.control.customer.server.control.CustomerControl;
028import com.echothree.model.control.customer.server.search.CustomerSearchEvaluator;
029import com.echothree.model.control.employee.server.control.EmployeeControl;
030import com.echothree.model.control.employee.server.search.EmployeeSearchEvaluator;
031import com.echothree.model.control.item.server.control.ItemControl;
032import com.echothree.model.control.item.server.search.ItemSearchEvaluator;
033import com.echothree.model.control.party.server.control.PartyControl;
034import com.echothree.model.control.search.common.SearchKinds;
035import com.echothree.model.control.search.common.SearchTypes;
036import com.echothree.model.control.search.server.control.SearchControl;
037import com.echothree.model.control.search.server.logic.SearchLogic;
038import com.echothree.model.control.security.common.SecurityRoleGroups;
039import com.echothree.model.control.security.common.SecurityRoles;
040import com.echothree.model.control.security.server.logic.SecurityRoleLogic;
041import com.echothree.model.control.vendor.server.control.VendorControl;
042import com.echothree.model.control.vendor.server.search.VendorSearchEvaluator;
043import com.echothree.model.control.warehouse.server.control.WarehouseControl;
044import com.echothree.model.control.warehouse.server.search.WarehouseSearchEvaluator;
045import com.echothree.model.data.party.server.entity.Party;
046import com.echothree.model.data.search.server.entity.SearchKind;
047import com.echothree.model.data.search.server.entity.SearchType;
048import com.echothree.model.data.user.common.pk.UserVisitPK;
049import com.echothree.model.data.user.server.entity.UserVisit;
050import com.echothree.util.common.command.BaseResult;
051import com.echothree.util.common.string.NameResult;
052import com.echothree.util.common.validation.FieldDefinition;
053import com.echothree.util.common.validation.FieldType;
054import com.echothree.util.server.control.BaseSimpleCommand;
055import com.echothree.util.server.message.DummyExecutionErrorAccumulator;
056import com.echothree.util.server.persistence.EntityNamesUtils;
057import com.echothree.util.server.persistence.Session;
058import com.echothree.util.server.persistence.translator.EntityInstanceAndNames;
059import com.echothree.util.server.string.NameCleaner;
060import java.util.Arrays;
061import java.util.Collections;
062import java.util.HashSet;
063import java.util.List;
064import java.util.Set;
065import javax.enterprise.context.RequestScoped;
066
067@RequestScoped
068public class IdentifyCommand
069        extends BaseSimpleCommand<IdentifyForm> {
070    
071    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
072    
073    static {
074        FORM_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
075                new FieldDefinition("Target", FieldType.STRING, true, null, null)
076                ));
077    }
078    
079    /** Creates a new instance of IdentifyCommand */
080    public IdentifyCommand() {
081        super(null, FORM_FIELD_DEFINITIONS, true);
082    }
083
084    @Override
085    protected void setupSession() {
086        super.setupSession();
087
088        // Names are always included in the JumpResult, assembly of them is a little weird, so always disallow this option.
089        removeOption(CoreOptions.EntityInstanceIncludeNames);
090
091        // Ensure we're able to compare instances of and generate a HashCode for the EntityInstanceTransfers
092        removeFilteredTransferProperty(EntityInstanceTransfer.class, CoreProperties.ENTITY_TYPE);
093        removeFilteredTransferProperty(EntityTypeTransfer.class, CoreProperties.COMPONENT_VENDOR);
094        removeFilteredTransferProperty(EntityTypeTransfer.class, CoreProperties.ENTITY_TYPE_NAME);
095        removeFilteredTransferProperty(ComponentVendorTransfer.class, CoreProperties.COMPONENT_VENDOR_NAME);
096    }
097    
098    private EntityInstanceTransfer fillInEntityInstance(EntityInstanceAndNames entityInstanceAndNames) {
099        var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
100        var entityInstance = entityInstanceControl.getEntityInstanceTransfer(getUserVisit(), entityInstanceAndNames.getEntityInstance(), false, false, false, false);
101
102        entityInstance.setEntityNames(entityInstanceAndNames.getEntityNames());
103        
104        return entityInstance;
105    }
106    
107    private void checkSequenceTypes(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
108        var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(this, party, target, true);
109        
110        if(entityInstanceAndNames != null) {
111            entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
112        }
113    }
114    
115    private void checkItems(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
116        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
117                SecurityRoleGroups.Item.name(), SecurityRoles.Search.name())) {
118            var itemControl = Session.getModelController(ItemControl.class);
119            var item = itemControl.getItemByNameThenAlias(target);
120
121            if(item != null) {
122                var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
123                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(item.getPrimaryKey());
124                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
125
126                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
127            }
128        }
129    }
130
131    private void checkCompanies(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
132        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
133                SecurityRoleGroups.Company.name(), SecurityRoles.Search.name())) {
134            var partyControl = Session.getModelController(PartyControl.class);
135            var partyCompany = partyControl.getPartyCompanyByName(target);
136
137            if(partyCompany != null) {
138                var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
139                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(partyCompany.getParty().getPrimaryKey());
140                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
141
142                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
143            }
144        }
145    }
146
147    private void checkDivisions(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
148        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
149                SecurityRoleGroups.Division.name(), SecurityRoles.Search.name())) {
150            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
151            var partyControl = Session.getModelController(PartyControl.class);
152            var partyDivisions = partyControl.getDivisionsByName(target);
153
154            partyDivisions.stream().map((partyDivision) -> entityInstanceControl.getEntityInstanceByBasePK(partyDivision.getParty().getPrimaryKey())).map((entityInstance) -> EntityNamesUtils.getInstance().getEntityNames(entityInstance)).forEach((entityInstanceAndNames) -> {
155                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
156            });
157        }
158    }
159
160    private void checkDepartments(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
161        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
162                SecurityRoleGroups.Department.name(), SecurityRoles.Search.name())) {
163            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
164            var partyControl = Session.getModelController(PartyControl.class);
165            var partyDepartments = partyControl.getDepartmentsByName(target);
166
167            partyDepartments.stream().map((partyDepartment) -> entityInstanceControl.getEntityInstanceByBasePK(partyDepartment.getParty().getPrimaryKey())).map((entityInstance) -> EntityNamesUtils.getInstance().getEntityNames(entityInstance)).forEach((entityInstanceAndNames) -> {
168                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
169            });
170        }
171    }
172
173    private void checkWarehouses(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
174        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
175                SecurityRoleGroups.Warehouse.name(), SecurityRoles.Search.name())) {
176            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
177            var warehouseControl = Session.getModelController(WarehouseControl.class);
178            var warehouse = warehouseControl.getWarehouseByName(target);
179
180            if(warehouse != null) {
181                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(warehouse.getParty().getPrimaryKey());
182                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
183
184                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
185            }
186        }
187    }
188
189    private void checkLocations(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
190        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
191                SecurityRoleGroups.Location.name(), SecurityRoles.Search.name())) {
192            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
193            var warehouseControl = Session.getModelController(WarehouseControl.class);
194            var locations = warehouseControl.getLocationsByName(target);
195
196            locations.stream().map((location) -> entityInstanceControl.getEntityInstanceByBasePK(location.getPrimaryKey())).map((entityInstance) -> EntityNamesUtils.getInstance().getEntityNames(entityInstance)).forEach((entityInstanceAndNames) -> {
197                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
198            });
199        }
200    }
201
202    private void checkEmployees(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
203        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
204                SecurityRoleGroups.Employee.name(), SecurityRoles.Search.name())) {
205            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
206            var employeeControl = Session.getModelController(EmployeeControl.class);
207            var partyEmployee = employeeControl.getPartyEmployeeByName(target);
208
209            if(partyEmployee != null) {
210                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(partyEmployee.getParty().getPrimaryKey());
211                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
212
213                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
214            }
215        }
216    }
217
218    private void checkCustomers(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
219        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
220                SecurityRoleGroups.Customer.name(), SecurityRoles.Search.name())) {
221            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
222            var customerControl = Session.getModelController(CustomerControl.class);
223            var customer = customerControl.getCustomerByName(target);
224
225            if(customer != null) {
226                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(customer.getParty().getPrimaryKey());
227                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
228
229                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
230            }
231        }
232    }
233
234    private void checkVendors(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
235        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
236                SecurityRoleGroups.Vendor.name(), SecurityRoles.Search.name())) {
237            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
238            var vendorControl = Session.getModelController(VendorControl.class);
239            var vendor = vendorControl.getVendorByName(target);
240
241            if(vendor != null) {
242                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(vendor.getParty().getPrimaryKey());
243                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
244
245                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
246            }
247        }
248    }
249
250    private void checkVendorItems(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
251        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
252                SecurityRoleGroups.VendorItem.name(), SecurityRoles.Search.name())) {
253            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
254            var vendorControl = Session.getModelController(VendorControl.class);
255            var vendorItems = vendorControl.getVendorItemsByVendorItemName(target);
256
257            vendorItems.stream().map((vendorItem) -> entityInstanceControl.getEntityInstanceByBasePK(vendorItem.getPrimaryKey())).map((entityInstance) -> EntityNamesUtils.getInstance().getEntityNames(entityInstance)).forEach((entityInstanceAndNames) -> {
258                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
259            });
260        }
261    }
262
263    private void checkComponentVendors(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
264        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
265                SecurityRoleGroups.ComponentVendor.name(), SecurityRoles.Search.name())) {
266            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
267            var componentVendor = componentControl.getComponentVendorByName(target);
268
269            if(componentVendor != null) {
270                var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(componentVendor.getPrimaryKey());
271                var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(entityInstance);
272
273                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
274            }
275        }
276    }
277
278    private void checkEntityTypes(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
279        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
280                SecurityRoleGroups.EntityType.name(), SecurityRoles.Search.name())) {
281            var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
282            var entityTypes = entityTypeControl.getEntityTypesByName(target);
283
284            entityTypes.stream().map((entityType) -> entityInstanceControl.getEntityInstanceByBasePK(entityType.getPrimaryKey())).map((entityInstance) -> EntityNamesUtils.getInstance().getEntityNames(entityInstance)).forEach((entityInstanceAndNames) -> {
285                entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
286            });
287        }
288    }
289
290    private void executeCustomerSearch(final UserVisit userVisit, final Set<EntityInstanceTransfer> entityInstances,
291            final SearchLogic searchLogic, final SearchKind searchKind, final SearchType searchType,
292            final String firstName, final String middleName, final String lastName, final String q) {
293        var customerSearchEvaluator = new CustomerSearchEvaluator(userVisit, searchType,
294                searchLogic.getDefaultSearchDefaultOperator(null),
295                searchLogic.getDefaultSearchSortOrder(null, searchKind),
296                searchLogic.getDefaultSearchSortDirection(null));
297
298        customerSearchEvaluator.setFirstName(firstName);
299        customerSearchEvaluator.setFirstNameSoundex(false);
300        customerSearchEvaluator.setMiddleName(middleName);
301        customerSearchEvaluator.setMiddleNameSoundex(false);
302        customerSearchEvaluator.setLastName(lastName);
303        customerSearchEvaluator.setLastNameSoundex(false);
304        customerSearchEvaluator.setQ(null, q);
305
306        // Avoid using the real ExecutionErrorAccumulator in order to avoid either throwing an Exception or
307        // accumulating errors for this UC.
308        var dummyExecutionErrorAccumulator = new DummyExecutionErrorAccumulator();
309        customerSearchEvaluator.execute(dummyExecutionErrorAccumulator);
310
311        if(!dummyExecutionErrorAccumulator.hasExecutionErrors()) {
312            addSearchResults(userVisit, searchType, entityInstances);
313        }
314    }
315
316    private void searchCustomers(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target,
317            final NameResult nameResult) {
318        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
319                SecurityRoleGroups.Customer.name(), SecurityRoles.Search.name())) {
320            var searchLogic = SearchLogic.getInstance();
321            var searchKind = searchLogic.getSearchKindByName(this, SearchKinds.CUSTOMER.name());
322
323            if(!hasExecutionErrors()) {
324                var searchType = searchLogic.getSearchTypeByName(this, searchKind, SearchTypes.IDENTIFY.name());
325
326                if(!hasExecutionErrors()) {
327                    var userVisit = getUserVisit();
328
329                    // First attempt using a first and/or last name isolated from target.
330                    executeCustomerSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
331                            nameResult.getFirstName(), nameResult.getMiddleName(), nameResult.getLastName(), null);
332                    // Then attempt searching for target using it as a query string.
333                    executeCustomerSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
334                            null, null, null, target);
335                }
336            }
337        }
338    }
339
340    private void executeEmployeeSearch(final UserVisit userVisit, final Set<EntityInstanceTransfer> entityInstances,
341            final SearchLogic searchLogic, final SearchKind searchKind, final SearchType searchType,
342            final String firstName, final String middleName, final String lastName, final String q) {
343        var employeeSearchEvaluator = new EmployeeSearchEvaluator(userVisit, searchType,
344                searchLogic.getDefaultSearchDefaultOperator(null),
345                searchLogic.getDefaultSearchSortOrder(null, searchKind),
346                searchLogic.getDefaultSearchSortDirection(null));
347
348        employeeSearchEvaluator.setFirstName(firstName);
349        employeeSearchEvaluator.setFirstNameSoundex(false);
350        employeeSearchEvaluator.setMiddleName(middleName);
351        employeeSearchEvaluator.setMiddleNameSoundex(false);
352        employeeSearchEvaluator.setLastName(lastName);
353        employeeSearchEvaluator.setLastNameSoundex(false);
354        employeeSearchEvaluator.setQ(null, q);
355
356        // Avoid using the real ExecutionErrorAccumulator in order to avoid either throwing an Exception or
357        // accumulating errors for this UC.
358        var dummyExecutionErrorAccumulator = new DummyExecutionErrorAccumulator();
359        employeeSearchEvaluator.execute(dummyExecutionErrorAccumulator);
360
361        if(!dummyExecutionErrorAccumulator.hasExecutionErrors()) {
362            addSearchResults(userVisit, searchType, entityInstances);
363        }
364    }
365
366    private void searchEmployees(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target,
367            final NameResult nameResult) {
368        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
369                SecurityRoleGroups.Employee.name(), SecurityRoles.Search.name())) {
370            var searchLogic = SearchLogic.getInstance();
371            var searchKind = searchLogic.getSearchKindByName(this, SearchKinds.EMPLOYEE.name());
372
373            if(!hasExecutionErrors()) {
374                var searchType = searchLogic.getSearchTypeByName(this, searchKind, SearchTypes.IDENTIFY.name());
375
376                if(!hasExecutionErrors()) {
377                    var userVisit = getUserVisit();
378
379                    // First attempt using a first and/or last name isolated from target.
380                    executeEmployeeSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
381                            nameResult.getFirstName(), nameResult.getMiddleName(), nameResult.getLastName(), null);
382                    // Then attempt searching for target using it as a query string.
383                    executeEmployeeSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
384                            null, null, null, target);
385                }
386            }
387        }
388    }
389
390    private void executeVendorSearch(final UserVisit userVisit, final Set<EntityInstanceTransfer> entityInstances,
391            final SearchLogic searchLogic, final SearchKind searchKind, final SearchType searchType,
392            final String firstName, final String middleName, final String lastName, final String q) {
393        var vendorSearchEvaluator = new VendorSearchEvaluator(userVisit, searchType,
394                searchLogic.getDefaultSearchDefaultOperator(null),
395                searchLogic.getDefaultSearchSortOrder(null, searchKind),
396                searchLogic.getDefaultSearchSortDirection(null));
397
398        vendorSearchEvaluator.setFirstName(firstName);
399        vendorSearchEvaluator.setFirstNameSoundex(false);
400        vendorSearchEvaluator.setMiddleName(middleName);
401        vendorSearchEvaluator.setMiddleNameSoundex(false);
402        vendorSearchEvaluator.setLastName(lastName);
403        vendorSearchEvaluator.setLastNameSoundex(false);
404        vendorSearchEvaluator.setQ(null, q);
405
406        // Avoid using the real ExecutionErrorAccumulator in order to avoid either throwing an Exception or
407        // accumulating errors for this UC.
408        var dummyExecutionErrorAccumulator = new DummyExecutionErrorAccumulator();
409        vendorSearchEvaluator.execute(dummyExecutionErrorAccumulator);
410
411        if(!dummyExecutionErrorAccumulator.hasExecutionErrors()) {
412            addSearchResults(userVisit, searchType, entityInstances);
413        }
414    }
415
416    private void searchVendors(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target,
417            final NameResult nameResult) {
418        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
419                SecurityRoleGroups.Vendor.name(), SecurityRoles.Search.name())) {
420            var searchLogic = SearchLogic.getInstance();
421            var searchKind = searchLogic.getSearchKindByName(this, SearchKinds.VENDOR.name());
422
423            if(!hasExecutionErrors()) {
424                var searchType = searchLogic.getSearchTypeByName(this, searchKind, SearchTypes.IDENTIFY.name());
425
426                if(!hasExecutionErrors()) {
427                    var userVisit = getUserVisit();
428
429                    // First attempt using a first and/or last name isolated from target.
430                    executeVendorSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
431                            nameResult.getFirstName(), nameResult.getMiddleName(), nameResult.getLastName(), null);
432                    // Then attempt searching for target using it as a query string.
433                    executeVendorSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
434                            null, null, null, target);
435                }
436            }
437        }
438    }
439
440    private void executeWarehouseSearch(final UserVisit userVisit, final Set<EntityInstanceTransfer> entityInstances,
441            final SearchLogic searchLogic, final SearchKind searchKind, final SearchType searchType, final String q) {
442        var warehouseSearchEvaluator = new WarehouseSearchEvaluator(userVisit, searchType,
443                searchLogic.getDefaultSearchDefaultOperator(null),
444                searchLogic.getDefaultSearchSortOrder(null, searchKind),
445                searchLogic.getDefaultSearchSortDirection(null));
446
447        warehouseSearchEvaluator.setQ(null, q);
448
449        // Avoid using the real ExecutionErrorAccumulator in order to avoid either throwing an Exception or
450        // accumulating errors for this UC.
451        var dummyExecutionErrorAccumulator = new DummyExecutionErrorAccumulator();
452        warehouseSearchEvaluator.execute(dummyExecutionErrorAccumulator);
453
454        if(!dummyExecutionErrorAccumulator.hasExecutionErrors()) {
455            addSearchResults(userVisit, searchType, entityInstances);
456        }
457    }
458
459    private void searchWarehouses(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
460        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
461                SecurityRoleGroups.Warehouse.name(), SecurityRoles.Search.name())) {
462            var searchLogic = SearchLogic.getInstance();
463            var searchKind = searchLogic.getSearchKindByName(this, SearchKinds.WAREHOUSE.name());
464
465            if(!hasExecutionErrors()) {
466                var searchType = searchLogic.getSearchTypeByName(this, searchKind, SearchTypes.IDENTIFY.name());
467
468                if(!hasExecutionErrors()) {
469                    var userVisit = getUserVisit();
470
471                    // Attempt searching for target using it as a query string.
472                    executeWarehouseSearch(userVisit, entityInstances, searchLogic, searchKind, searchType,
473                            target);
474                }
475            }
476        }
477    }
478
479    private void executeItemSearch(final UserVisit userVisit, final Set<EntityInstanceTransfer> entityInstances,
480            final SearchLogic searchLogic, final SearchKind searchKind, final SearchType searchType,
481            final String q) {
482        var itemSearchEvaluator = new ItemSearchEvaluator(userVisit, null, searchType,
483                searchLogic.getDefaultSearchDefaultOperator(null),
484                searchLogic.getDefaultSearchSortOrder(null, searchKind),
485                searchLogic.getDefaultSearchSortDirection(null),
486                null);
487
488        itemSearchEvaluator.setQ(null, q);
489
490        // Avoid using the real ExecutionErrorAccumulator in order to avoid either throwing an Exception or
491        // accumulating errors for this UC.
492        var dummyExecutionErrorAccumulator = new DummyExecutionErrorAccumulator();
493        itemSearchEvaluator.execute(dummyExecutionErrorAccumulator);
494
495        if(!dummyExecutionErrorAccumulator.hasExecutionErrors()) {
496            addSearchResults(userVisit, searchType, entityInstances);
497        }
498    }
499
500    private void searchItems(final Party party, final Set<EntityInstanceTransfer> entityInstances, final String target) {
501        if(SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(this, party,
502                SecurityRoleGroups.Item.name(), SecurityRoles.Search.name())) {
503            var searchLogic = SearchLogic.getInstance();
504            var searchKind = searchLogic.getSearchKindByName(this, SearchKinds.ITEM.name());
505
506            if(!hasExecutionErrors()) {
507                var searchType = searchLogic.getSearchTypeByName(this, searchKind, SearchTypes.IDENTIFY.name());
508
509                if(!hasExecutionErrors()) {
510                    var userVisit = getUserVisit();
511
512                    executeItemSearch(userVisit, entityInstances, searchLogic, searchKind, searchType, target);
513                }
514            }
515        }
516    }
517
518    // Add results from any of the BaseSearchEvaluators to the entityInstances.
519    private void addSearchResults(final UserVisit userVisit, final SearchType searchType,
520            final Set<EntityInstanceTransfer> entityInstances) {
521        var searchControl = Session.getModelController(SearchControl.class);
522        var userVisitSearch = SearchLogic.getInstance().getUserVisitSearch(null, userVisit, searchType);
523        var resultEntityInstances = searchControl.getUserVisitSearchEntityInstances(userVisitSearch);
524
525        for(var resultEntityInstance : resultEntityInstances) {
526            var entityInstanceAndNames = EntityNamesUtils.getInstance().getEntityNames(resultEntityInstance);
527
528            entityInstances.add(fillInEntityInstance(entityInstanceAndNames));
529        }
530    }
531
532    @Override
533    protected BaseResult execute() {
534        var result = SearchResultFactory.getIdentifyResult();
535        var entityInstances = new HashSet<EntityInstanceTransfer>();
536        var target = form.getTarget();
537        var party = getParty();
538        
539        // Compile a list of all possible EntityInstances that the target may refer to.
540        checkSequenceTypes(party, entityInstances, target); // uses EEA
541        if(!hasExecutionErrors()) {
542            checkItems(party, entityInstances, target); // uses EEA
543        }
544        if(!hasExecutionErrors()) {
545            checkCompanies(party, entityInstances, target); // uses EEA
546        }
547        if(!hasExecutionErrors()) {
548            checkDivisions(party, entityInstances, target); // uses EEA
549        }
550        if(!hasExecutionErrors()) {
551            checkDepartments(party, entityInstances, target); // uses EEA
552        }
553        if(!hasExecutionErrors()) {
554            checkWarehouses(party, entityInstances, target); // uses EEA
555        }
556        if(!hasExecutionErrors()) {
557            checkLocations(party, entityInstances, target); // uses EEA
558        }
559        if(!hasExecutionErrors()) {
560            checkEmployees(party, entityInstances, target); // uses EEA
561        }
562        if(!hasExecutionErrors()) {
563            checkCustomers(party, entityInstances, target); // uses EEA
564        }
565        if(!hasExecutionErrors()) {
566            checkVendors(party, entityInstances, target); // uses EEA
567        }
568        if(!hasExecutionErrors()) {
569            checkVendorItems(party, entityInstances, target); // uses EEA
570        }
571        if(!hasExecutionErrors()) {
572            checkComponentVendors(party, entityInstances, target); // uses EEA
573        }
574        if(!hasExecutionErrors()) {
575            checkEntityTypes(party, entityInstances, target); // uses EEA
576        }
577
578        var nameResult = new NameCleaner().getCleansedName(target);
579        if(!hasExecutionErrors()) {
580            searchEmployees(party, entityInstances, target, nameResult); // uses EEA
581        }
582        if(!hasExecutionErrors()) {
583            searchCustomers(party, entityInstances, target, nameResult); // uses EEA
584        }
585        if(!hasExecutionErrors()) {
586            searchVendors(party, entityInstances, target, nameResult); // uses EEA
587        }
588        if(!hasExecutionErrors()) {
589            searchWarehouses(party, entityInstances, target); // uses EEA
590        }
591        if(!hasExecutionErrors()) {
592            searchItems(party, entityInstances, target); // uses EEA
593        }
594
595        result.setEntityInstances(entityInstances);
596        
597        return result;
598    }
599    
600}