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.search.server.command; 018 019import com.echothree.control.user.search.common.form.SearchCustomersForm; 020import com.echothree.control.user.search.common.result.SearchCustomersResult; 021import com.echothree.control.user.search.common.result.SearchResultFactory; 022import com.echothree.model.control.customer.server.control.CustomerControl; 023import com.echothree.model.control.geo.server.control.GeoControl; 024import com.echothree.model.control.party.common.PartyTypes; 025import com.echothree.model.control.party.server.control.PartyControl; 026import com.echothree.model.control.search.common.SearchKinds; 027import com.echothree.model.control.search.server.control.SearchControl; 028import com.echothree.model.control.customer.server.search.CustomerSearchEvaluator; 029import com.echothree.model.control.search.server.logic.SearchLogic; 030import com.echothree.model.control.security.common.SecurityRoleGroups; 031import com.echothree.model.control.security.common.SecurityRoles; 032import com.echothree.model.data.customer.server.entity.CustomerType; 033import com.echothree.model.data.geo.server.entity.GeoCode; 034import com.echothree.model.data.geo.server.entity.GeoCodeCountry; 035import com.echothree.model.data.party.server.entity.PartyAliasType; 036import com.echothree.model.data.party.server.entity.PartyType; 037import com.echothree.model.data.search.server.entity.SearchKind; 038import com.echothree.model.data.search.server.entity.SearchType; 039import com.echothree.model.data.user.common.pk.UserVisitPK; 040import com.echothree.model.data.user.server.entity.UserVisit; 041import com.echothree.util.common.message.ExecutionErrors; 042import com.echothree.util.common.string.StringUtils; 043import com.echothree.util.common.validation.FieldDefinition; 044import com.echothree.util.common.validation.FieldType; 045import com.echothree.util.common.command.BaseResult; 046import com.echothree.util.common.form.ValidationResult; 047import com.echothree.util.server.control.BaseSimpleCommand; 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 com.echothree.util.server.validation.Validator; 053import com.google.common.base.Splitter; 054import java.util.Arrays; 055import java.util.Collections; 056import java.util.List; 057import java.util.Locale; 058import java.util.regex.Pattern; 059 060public class SearchCustomersCommand 061 extends BaseSimpleCommand<SearchCustomersForm> { 062 063 private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION; 064 private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS; 065 private final static List<FieldDefinition> formAliasFieldDefinitions; 066 067 static { 068 COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(Collections.unmodifiableList(Arrays.asList( 069 new PartyTypeDefinition(PartyTypes.UTILITY.name(), null), 070 new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), Collections.unmodifiableList(Arrays.asList( 071 new SecurityRoleDefinition(SecurityRoleGroups.Customer.name(), SecurityRoles.Search.name()) 072 ))) 073 ))); 074 075 FORM_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList( 076 new FieldDefinition("SearchTypeName", FieldType.ENTITY_NAME, true, null, null), 077 new FieldDefinition("CustomerTypeName", FieldType.ENTITY_NAME, false, null, null), 078 new FieldDefinition("FirstName", FieldType.STRING, false, 1L, 20L), 079 new FieldDefinition("FirstNameSoundex", FieldType.BOOLEAN, false, null, null), 080 new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L), 081 new FieldDefinition("MiddleNameSoundex", FieldType.BOOLEAN, false, null, null), 082 new FieldDefinition("LastName", FieldType.STRING, false, 1L, 20L), 083 new FieldDefinition("LastNameSoundex", FieldType.BOOLEAN, false, null, null), 084 new FieldDefinition("Name", FieldType.STRING, false, null, null), 085 new FieldDefinition("CountryName", FieldType.ENTITY_NAME, false, null, null), 086 new FieldDefinition("AreaCode", FieldType.STRING, false, 1L, 5L), 087 new FieldDefinition("TelephoneNumber", FieldType.STRING, false, 1L, 25L), 088 new FieldDefinition("TelephoneExtension", FieldType.NUMBERS, false, 1L, 10L), 089 new FieldDefinition("EmailAddress", FieldType.EMAIL_ADDRESS, false, null, null), 090 new FieldDefinition("CustomerName", FieldType.ENTITY_NAME, false, null, null), 091 new FieldDefinition("PartyName", FieldType.ENTITY_NAME, false, null, null), 092 new FieldDefinition("PartyAliasTypeName", FieldType.ENTITY_NAME, false, null, null), 093 new FieldDefinition("Alias", FieldType.ENTITY_NAME, false, null, null), 094 new FieldDefinition("CreatedSince", FieldType.DATE_TIME, false, null, null), 095 new FieldDefinition("ModifiedSince", FieldType.DATE_TIME, false, null, null), 096 new FieldDefinition("Fields", FieldType.STRING, false, null, null) 097 )); 098 099 formAliasFieldDefinitions = Collections.unmodifiableList(Arrays.asList( 100 new FieldDefinition("Alias", FieldType.ENTITY_NAME, true, null, null) 101 )); 102 } 103 104 /** Creates a new instance of SearchCustomersCommand */ 105 public SearchCustomersCommand(UserVisitPK userVisitPK, SearchCustomersForm form) { 106 super(userVisitPK, form, COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false); 107 } 108 109 @Override 110 protected ValidationResult validate() { 111 Validator validator = new Validator(this); 112 ValidationResult validationResult = validator.validate(form, FORM_FIELD_DEFINITIONS); 113 114 if(!validationResult.getHasErrors()) { 115 String partyAliasTypeName = form.getPartyAliasTypeName(); 116 117 if(partyAliasTypeName != null) { 118 validationResult = validator.validate(form, formAliasFieldDefinitions); 119 } 120 } 121 122 return validationResult; 123 } 124 125 @Override 126 protected BaseResult execute() { 127 var searchControl = Session.getModelController(SearchControl.class); 128 SearchCustomersResult result = SearchResultFactory.getSearchCustomersResult(); 129 SearchKind searchKind = searchControl.getSearchKindByName(SearchKinds.CUSTOMER.name()); 130 131 if(searchKind != null) { 132 String searchTypeName = form.getSearchTypeName(); 133 SearchType searchType = searchControl.getSearchTypeByName(searchKind, searchTypeName); 134 135 if(searchType != null) { 136 var customerControl = Session.getModelController(CustomerControl.class); 137 String customerTypeName = form.getCustomerTypeName(); 138 CustomerType customerType = customerTypeName == null? null: customerControl.getCustomerTypeByName(customerTypeName); 139 140 if(customerTypeName == null || customerType != null) { 141 String partyAliasTypeName = form.getPartyAliasTypeName(); 142 String alias = form.getAlias(); 143 PartyAliasType partyAliasType = null; 144 145 if(partyAliasTypeName != null) { 146 var partyControl = Session.getModelController(PartyControl.class); 147 PartyType partyType = partyControl.getPartyTypeByName(PartyTypes.CUSTOMER.name()); 148 149 if(partyType != null) { 150 partyAliasType = partyControl.getPartyAliasTypeByName(partyType, partyAliasTypeName); 151 152 if(partyAliasType == null) { 153 addExecutionError(ExecutionErrors.UnknownPartyAliasTypeName.name(), PartyTypes.CUSTOMER.name(), partyAliasTypeName); 154 } 155 } else { 156 addExecutionError(ExecutionErrors.UnknownPartyTypeName.name(), PartyTypes.CUSTOMER.name()); 157 } 158 } 159 160 if(!hasExecutionErrors()) { 161 var geoControl = Session.getModelController(GeoControl.class); 162 String countryName = form.getCountryName(); 163 String countryAlias = countryName == null ? null : StringUtils.getInstance().cleanStringToName(countryName).toUpperCase(Locale.getDefault()); 164 GeoCode countryGeoCode = countryAlias == null ? null : geoControl.getCountryByAlias(countryAlias); 165 166 if(countryName == null || countryGeoCode != null) { 167 GeoCodeCountry geoCodeCountry = countryGeoCode == null ? null : geoControl.getGeoCodeCountry(countryGeoCode); 168 String areaCode = form.getAreaCode(); 169 String areaCodePattern = geoCodeCountry == null ? null : geoCodeCountry.getAreaCodePattern(); 170 Pattern pattern = areaCodePattern == null ? null : Pattern.compile(areaCodePattern); 171 172 if(areaCode == null || (pattern == null || pattern.matcher(areaCode).matches())) { 173 String telephoneNumberPattern = countryGeoCode == null ? null : geoCodeCountry.getTelephoneNumberPattern(); 174 String telephoneNumber = form.getTelephoneNumber(); 175 176 pattern = telephoneNumberPattern == null ? null : Pattern.compile(telephoneNumberPattern); 177 178 if(telephoneNumber == null || (pattern == null || pattern.matcher(telephoneNumber).matches())) { 179 SearchLogic searchLogic = SearchLogic.getInstance(); 180 UserVisit userVisit = getUserVisit(); 181 CustomerSearchEvaluator customerSearchEvaluator = new CustomerSearchEvaluator(userVisit, searchType, 182 searchLogic.getDefaultSearchDefaultOperator(null), searchLogic.getDefaultSearchSortOrder(null, searchKind), 183 searchLogic.getDefaultSearchSortDirection(null)); 184 String createdSince = form.getCreatedSince(); 185 String modifiedSince = form.getModifiedSince(); 186 String fields = form.getFields(); 187 188 customerSearchEvaluator.setFirstName(form.getFirstName()); 189 customerSearchEvaluator.setFirstNameSoundex(Boolean.parseBoolean(form.getFirstNameSoundex())); 190 customerSearchEvaluator.setMiddleName(form.getMiddleName()); 191 customerSearchEvaluator.setMiddleNameSoundex(Boolean.parseBoolean(form.getMiddleNameSoundex())); 192 customerSearchEvaluator.setLastName(form.getLastName()); 193 customerSearchEvaluator.setLastNameSoundex(Boolean.parseBoolean(form.getLastNameSoundex())); 194 customerSearchEvaluator.setQ(this, form.getName()); 195 customerSearchEvaluator.setCountryGeoCode(countryGeoCode); 196 customerSearchEvaluator.setAreaCode(areaCode); 197 customerSearchEvaluator.setTelephoneNumber(telephoneNumber); 198 customerSearchEvaluator.setTelephoneExtension(form.getTelephoneExtension()); 199 customerSearchEvaluator.setEmailAddress(form.getEmailAddress()); 200 customerSearchEvaluator.setCustomerType(customerType); 201 customerSearchEvaluator.setPartyAliasType(partyAliasType); 202 customerSearchEvaluator.setAlias(alias); 203 customerSearchEvaluator.setCustomerName(form.getCustomerName()); 204 customerSearchEvaluator.setPartyName(form.getPartyName()); 205 customerSearchEvaluator.setCreatedSince(createdSince == null ? null : Long.valueOf(createdSince)); 206 customerSearchEvaluator.setModifiedSince(modifiedSince == null ? null : Long.valueOf(modifiedSince)); 207 customerSearchEvaluator.setFields(fields == null ? null : Splitter.on(':').trimResults().omitEmptyStrings().splitToList(fields).toArray(new String[0])); 208 209 if(!hasExecutionErrors()) { 210 result.setCount(customerSearchEvaluator.execute(this)); 211 } 212 } else { 213 addExecutionError(ExecutionErrors.InvalidTelephoneNumber.name(), telephoneNumber); 214 } 215 } else { 216 addExecutionError(ExecutionErrors.InvalidAreaCode.name(), areaCode); 217 } 218 } else { 219 addExecutionError(ExecutionErrors.UnknownCountryName.name(), countryName); 220 } 221 } 222 } else { 223 addExecutionError(ExecutionErrors.UnknownCustomerTypeName.name(), customerTypeName); 224 } 225 } else { 226 addExecutionError(ExecutionErrors.UnknownSearchTypeName.name(), SearchKinds.CUSTOMER.name(), searchTypeName); 227 } 228 } else { 229 addExecutionError(ExecutionErrors.UnknownSearchKindName.name(), SearchKinds.CUSTOMER.name()); 230 } 231 232 return result; 233 } 234}