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.model.control.party.server.search; 018 019import com.echothree.model.control.core.common.ComponentVendors; 020import com.echothree.model.control.core.common.EntityTypes; 021import com.echothree.model.control.index.common.IndexFields; 022import com.echothree.model.control.index.server.analysis.ItemAnalyzer; 023import com.echothree.model.control.index.server.analysis.PartyAnalyzer; 024import com.echothree.model.control.party.server.control.PartyControl; 025import com.echothree.model.control.party.server.logic.PartyLogic; 026import com.echothree.model.control.search.server.search.BaseSearchEvaluator; 027import com.echothree.model.control.search.server.search.EntityInstancePKHolder; 028import com.echothree.model.data.core.server.factory.EntityInstanceFactory; 029import com.echothree.model.data.geo.server.entity.GeoCode; 030import com.echothree.model.data.party.server.entity.Language; 031import com.echothree.model.data.party.server.entity.Party; 032import com.echothree.model.data.party.server.entity.PartyAliasType; 033import com.echothree.model.data.party.server.entity.PartyType; 034import com.echothree.model.data.search.server.entity.SearchDefaultOperator; 035import com.echothree.model.data.search.server.entity.SearchSortDirection; 036import com.echothree.model.data.search.server.entity.SearchSortOrder; 037import com.echothree.model.data.search.server.entity.SearchType; 038import com.echothree.model.data.user.server.entity.UserVisit; 039import com.echothree.util.server.message.ExecutionErrorAccumulator; 040import com.echothree.util.server.persistence.Session; 041import org.apache.lucene.analysis.Analyzer; 042 043public class PartySearchEvaluator 044 extends BaseSearchEvaluator { 045 046 protected PartyType partyType; 047 protected String entityNameIndexField; 048 private String firstName; 049 private Boolean firstNameSoundex; 050 private String middleName; 051 private Boolean middleNameSoundex; 052 private String lastName; 053 private Boolean lastNameSoundex; 054 private GeoCode countryGeoCode; 055 private String areaCode; 056 private String telephoneNumber; 057 private String telephoneExtension; 058 private String emailAddress; 059 private String partyName; 060 private PartyAliasType partyAliasType; 061 private String alias; 062 063 protected PartySearchEvaluator(UserVisit userVisit, SearchType searchType, SearchDefaultOperator searchDefaultOperator, SearchSortOrder searchSortOrder, 064 SearchSortDirection searchSortDirection, String partyTypeName, final String entityNameIndexField, String indexName) { 065 super(userVisit, searchDefaultOperator, searchType, searchSortOrder, searchSortDirection, null, ComponentVendors.ECHO_THREE.name(), 066 EntityTypes.Party.name(), null, null, indexName); 067 068 this.partyType = PartyLogic.getInstance().getPartyTypeByName(null, partyTypeName); 069 this.entityNameIndexField = entityNameIndexField; 070 071 setField(IndexFields.name.name()); 072 } 073 074 @Override 075 public EntityInstancePKHolder getEntityInstancePKHolderByCreatedTime(Long createdTime) { 076 // Custom version for PartySearchEvaluator that takes into account the PartyType. 077 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 078 "SELECT _PK_ " 079 + "FROM entityinstances, entitytimes, parties, partydetails " 080 + "WHERE par_activedetailid = pardt_partydetailid AND pardt_ptyp_partytypeid = ? " 081 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid " 082 + "AND eni_entityinstanceid = etim_eni_entityinstanceid AND etim_createdtime >= ?"), 083 partyType, entityType, createdTime); 084 } 085 086 @Override 087 public EntityInstancePKHolder getEntityInstancePKHolderByModifiedTime(Long modifiedTime) { 088 // Custom version for PartySearchEvaluator that takes into account the PartyType. 089 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 090 "SELECT _PK_ " 091 + "FROM entityinstances, entitytimes, parties, partydetails " 092 + "WHERE par_activedetailid = pardt_partydetailid AND pardt_ptyp_partytypeid = ? " 093 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid " 094 + "AND eni_entityinstanceid = etim_eni_entityinstanceid AND etim_modifiedtime >= ?"), 095 partyType, entityType, modifiedTime); 096 } 097 098 public EntityInstancePKHolder getEntityInstancePKHolderByFirstName(String firstName) { 099 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 100 "SELECT _PK_ " 101 + "FROM entityinstances, parties, partydetails, people " 102 + "WHERE par_activedetailid = pardt_partydetailid " 103 + "AND pardt_ptyp_partytypeid = ? " 104 + "AND par_partyid = peop_par_partyid AND peop_firstname = ? AND peop_thrutime = ? " 105 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 106 partyType, firstName, Session.MAX_TIME, entityType); 107 } 108 109 public EntityInstancePKHolder getEntityInstancePKHolderByFirstNameSdx(String firstNameSdx) { 110 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 111 "SELECT _PK_ " 112 + "FROM entityinstances, parties, partydetails, people " 113 + "WHERE par_activedetailid = pardt_partydetailid " 114 + "AND pardt_ptyp_partytypeid = ? " 115 + "AND par_partyid = peop_par_partyid AND peop_firstnamesdx = ? AND peop_thrutime = ? " 116 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 117 partyType, firstNameSdx, Session.MAX_TIME, entityType); 118 } 119 120 public EntityInstancePKHolder getEntityInstancePKHolderByMiddleName(String middleName) { 121 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 122 "SELECT _PK_ " 123 + "FROM entityinstances, parties, partydetails, people " 124 + "WHERE par_activedetailid = pardt_partydetailid " 125 + "AND pardt_ptyp_partytypeid = ? " 126 + "AND par_partyid = peop_par_partyid AND peop_middlename = ? AND peop_thrutime = ? " 127 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 128 partyType, middleName, Session.MAX_TIME, entityType); 129 } 130 131 public EntityInstancePKHolder getEntityInstancePKHolderByMiddleNameSdx(String middleNameSdx) { 132 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 133 "SELECT _PK_ " 134 + "FROM entityinstances, parties, partydetails, people " 135 + "WHERE par_activedetailid = pardt_partydetailid " 136 + "AND pardt_ptyp_partytypeid = ? " 137 + "AND par_partyid = peop_par_partyid AND peop_middlenamesdx = ? AND peop_thrutime = ? " 138 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 139 partyType, middleNameSdx, Session.MAX_TIME, entityType); 140 } 141 142 public EntityInstancePKHolder getEntityInstancePKHolderByLastName(String lastName) { 143 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 144 "SELECT _PK_ " 145 + "FROM entityinstances, parties, partydetails, people " 146 + "WHERE par_activedetailid = pardt_partydetailid " 147 + "AND pardt_ptyp_partytypeid = ? " 148 + "AND par_partyid = peop_par_partyid AND peop_lastname = ? AND peop_thrutime = ? " 149 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 150 partyType, lastName, Session.MAX_TIME, entityType); 151 } 152 153 public EntityInstancePKHolder getEntityInstancePKHolderByLastNameSdx(String lastNameSdx) { 154 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 155 "SELECT _PK_ " 156 + "FROM entityinstances, parties, partydetails, people " 157 + "WHERE par_activedetailid = pardt_partydetailid " 158 + "AND pardt_ptyp_partytypeid = ? " 159 + "AND par_partyid = peop_par_partyid AND peop_lastnamesdx = ? AND peop_thrutime = ? " 160 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 161 partyType, lastNameSdx, Session.MAX_TIME, entityType); 162 } 163 164 public EntityInstancePKHolder getEntityInstancePKHolderByAreaCode(GeoCode countryGeoCode, String areaCode) { 165 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 166 "SELECT _PK_ " 167 + "FROM entityinstances, parties, partydetails, partycontactmechanisms, partycontactmechanismdetails, contacttelephones " 168 + "WHERE par_activedetailid = pardt_partydetailid " 169 + "AND pardt_ptyp_partytypeid = ? " 170 + "AND pcm_activedetailid = pcmdt_partycontactmechanismdetailid " 171 + "AND par_partyid = pcmdt_par_partyid " 172 + "AND pcmdt_cmch_contactmechanismid = cttp_cmch_contactmechanismid AND cttp_thrutime = ? " 173 + "AND cttp_countrygeocodeid = ? AND cttp_areacode = ? " 174 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 175 partyType, Session.MAX_TIME, countryGeoCode, areaCode, entityType); 176 } 177 178 public EntityInstancePKHolder getEntityInstancePKHolderByTelephoneNumber(GeoCode countryGeoCode, String telephoneNumber) { 179 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 180 "SELECT _PK_ " 181 + "FROM entityinstances, parties, partydetails, partycontactmechanisms, partycontactmechanismdetails, contacttelephones " 182 + "WHERE par_activedetailid = pardt_partydetailid " 183 + "AND pardt_ptyp_partytypeid = ? " 184 + "AND pcm_activedetailid = pcmdt_partycontactmechanismdetailid " 185 + "AND par_partyid = pcmdt_par_partyid " 186 + "AND pcmdt_cmch_contactmechanismid = cttp_cmch_contactmechanismid AND cttp_thrutime = ? " 187 + "AND cttp_countrygeocodeid = ? AND cttp_telephonenumber = ? " 188 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 189 partyType, Session.MAX_TIME, countryGeoCode, telephoneNumber, entityType); 190 } 191 192 public EntityInstancePKHolder getEntityInstancePKHolderByTelephoneExtension(GeoCode countryGeoCode, String telephoneExtension) { 193 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 194 "SELECT _PK_ " 195 + "FROM entityinstances, parties, partydetails, partycontactmechanisms, partycontactmechanismdetails, contacttelephones " 196 + "WHERE par_activedetailid = pardt_partydetailid " 197 + "AND pardt_ptyp_partytypeid = ? " 198 + "AND pcm_activedetailid = pcmdt_partycontactmechanismdetailid " 199 + "AND par_partyid = pcmdt_par_partyid " 200 + "AND pcmdt_cmch_contactmechanismid = cttp_cmch_contactmechanismid AND cttp_thrutime = ? " 201 + "AND cttp_countrygeocodeid = ? AND cttp_telephoneextension = ? " 202 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 203 partyType, Session.MAX_TIME, countryGeoCode, telephoneExtension, entityType); 204 } 205 206 public EntityInstancePKHolder getEntityInstancePKHolderByEmailAddress(String emailAddress) { 207 return getEntityInstancePKHolderFromQuery(EntityInstanceFactory.getInstance().prepareStatement( 208 "SELECT _PK_ " 209 + "FROM entityinstances, parties, partydetails, partycontactmechanisms, partycontactmechanismdetails, contactemailaddresses " 210 + "WHERE par_activedetailid = pardt_partydetailid " 211 + "AND pardt_ptyp_partytypeid = ? " 212 + "AND pcm_activedetailid = pcmdt_partycontactmechanismdetailid " 213 + "AND par_partyid = pcmdt_par_partyid " 214 + "AND pcmdt_cmch_contactmechanismid = ctea_cmch_contactmechanismid AND ctea_thrutime = ? " 215 + "AND ctea_emailaddress = ? " 216 + "AND eni_ent_entitytypeid = ? AND par_partyid = eni_entityuniqueid"), 217 partyType, Session.MAX_TIME, emailAddress, entityType); 218 } 219 220 public String getFirstName() { 221 return firstName; 222 } 223 224 public void setFirstName(String firstName) { 225 this.firstName = firstName; 226 } 227 228 public Boolean getFirstNameSoundex() { 229 return firstNameSoundex; 230 } 231 232 public void setFirstNameSoundex(Boolean firstNameSoundex) { 233 this.firstNameSoundex = firstNameSoundex; 234 } 235 236 public String getMiddleName() { 237 return middleName; 238 } 239 240 public void setMiddleName(String middleName) { 241 this.middleName = middleName; 242 } 243 244 public Boolean getMiddleNameSoundex() { 245 return middleNameSoundex; 246 } 247 248 public void setMiddleNameSoundex(Boolean middleNameSoundex) { 249 this.middleNameSoundex = middleNameSoundex; 250 } 251 252 public String getLastName() { 253 return lastName; 254 } 255 256 public void setLastName(String lastName) { 257 this.lastName = lastName; 258 } 259 260 public Boolean getLastNameSoundex() { 261 return lastNameSoundex; 262 } 263 264 public void setLastNameSoundex(Boolean lastNameSoundex) { 265 this.lastNameSoundex = lastNameSoundex; 266 } 267 268 public String getPartyName() { 269 return partyName; 270 } 271 272 public GeoCode getCountryGeoCode() { 273 return countryGeoCode; 274 } 275 276 public void setCountryGeoCode(GeoCode countryGeoCode) { 277 this.countryGeoCode = countryGeoCode; 278 } 279 280 public String getAreaCode() { 281 return areaCode; 282 } 283 284 public void setAreaCode(String areaCode) { 285 this.areaCode = areaCode; 286 } 287 288 public String getTelephoneNumber() { 289 return telephoneNumber; 290 } 291 292 public void setTelephoneNumber(String telephoneNumber) { 293 this.telephoneNumber = telephoneNumber; 294 } 295 296 public String getTelephoneExtension() { 297 return telephoneExtension; 298 } 299 300 public void setTelephoneExtension(String telephoneExtension) { 301 this.telephoneExtension = telephoneExtension; 302 } 303 304 public String getEmailAddress() { 305 return emailAddress; 306 } 307 308 public void setEmailAddress(String emailAddress) { 309 this.emailAddress = emailAddress; 310 } 311 312 public void setPartyName(String partyName) { 313 this.partyName = partyName; 314 } 315 316 public PartyAliasType getPartyAliasType() { 317 return partyAliasType; 318 } 319 320 public void setPartyAliasType(PartyAliasType partyAliasType) { 321 this.partyAliasType = partyAliasType; 322 } 323 324 public String getAlias() { 325 return alias; 326 } 327 328 public void setAlias(String alias) { 329 this.alias = alias; 330 } 331 332 @Override 333 public Analyzer getAnalyzer(final ExecutionErrorAccumulator eea, final Language language) { 334 return new PartyAnalyzer(eea, language, entityType, partyType, entityNameIndexField); 335 } 336 337 /** Subclasses should override and always call their super's executeSearch() */ 338 @Override 339 protected EntityInstancePKHolder executeSearch(final ExecutionErrorAccumulator eea) { 340 EntityInstancePKHolder resultSet = null; 341 var parameterCount = (partyName == null ? 0 : 1) + (alias == null ? 0 : 1); 342 343 if(parameterCount == 0) { 344 resultSet = super.executeSearch(eea); 345 346 if(resultSet == null || resultSet.size() > 0) { 347 if(firstName != null) { 348 if(firstNameSoundex) { 349 String firstNameSdx; 350 351 try { 352 firstNameSdx = firstName == null? null: getSoundex().encode(firstName); 353 } catch (IllegalArgumentException iae) { 354 firstNameSdx = null; 355 } 356 357 if(firstNameSdx != null) { 358 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByFirstNameSdx(firstNameSdx); 359 360 if(resultSet == null) { 361 resultSet = entityInstancePKHolder; 362 } else { 363 resultSet.retainAll(entityInstancePKHolder); 364 } 365 } else { 366 resultSet = null; 367 } 368 } else { 369 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByFirstName(firstName); 370 371 if(resultSet == null) { 372 resultSet = entityInstancePKHolder; 373 } else { 374 resultSet.retainAll(entityInstancePKHolder); 375 } 376 } 377 } 378 } 379 380 if(resultSet == null || resultSet.size() > 0) { 381 if(middleName != null) { 382 if(middleNameSoundex) { 383 String middleNameSdx; 384 385 try { 386 middleNameSdx = middleName == null? null: getSoundex().encode(middleName); 387 } catch (IllegalArgumentException iae) { 388 middleNameSdx = null; 389 } 390 391 if(middleNameSdx != null) { 392 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByMiddleNameSdx(middleNameSdx); 393 394 if(resultSet == null) { 395 resultSet = entityInstancePKHolder; 396 } else { 397 resultSet.retainAll(entityInstancePKHolder); 398 } 399 } else { 400 resultSet = null; 401 } 402 } else { 403 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByMiddleName(middleName); 404 405 if(resultSet == null) { 406 resultSet = entityInstancePKHolder; 407 } else { 408 resultSet.retainAll(entityInstancePKHolder); 409 } 410 } 411 } 412 } 413 414 if(resultSet == null || resultSet.size() > 0) { 415 if(lastName != null) { 416 if(lastNameSoundex) { 417 String lastNameSdx; 418 419 try { 420 lastNameSdx = lastName == null? null: getSoundex().encode(lastName); 421 } catch (IllegalArgumentException iae) { 422 lastNameSdx = null; 423 } 424 425 if(lastNameSdx != null) { 426 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByLastNameSdx(lastNameSdx); 427 428 if(resultSet == null) { 429 resultSet = entityInstancePKHolder; 430 } else { 431 resultSet.retainAll(entityInstancePKHolder); 432 } 433 } else { 434 resultSet = null; 435 } 436 } else { 437 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByLastName(lastName); 438 439 if(resultSet == null) { 440 resultSet = entityInstancePKHolder; 441 } else { 442 resultSet.retainAll(entityInstancePKHolder); 443 } 444 } 445 } 446 } 447 448 if(countryGeoCode != null && areaCode != null && (resultSet == null || resultSet.size() > 0)) { 449 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByAreaCode(countryGeoCode, areaCode); 450 451 if(resultSet == null) { 452 resultSet = entityInstancePKHolder; 453 } else { 454 resultSet.retainAll(entityInstancePKHolder); 455 } 456 } 457 458 if(countryGeoCode != null && telephoneNumber != null && (resultSet == null || resultSet.size() > 0)) { 459 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByTelephoneNumber(countryGeoCode, telephoneNumber); 460 461 if(resultSet == null) { 462 resultSet = entityInstancePKHolder; 463 } else { 464 resultSet.retainAll(entityInstancePKHolder); 465 } 466 } 467 468 if(countryGeoCode != null && telephoneExtension != null && (resultSet == null || resultSet.size() > 0)) { 469 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByTelephoneExtension(countryGeoCode, telephoneExtension); 470 471 if(resultSet == null) { 472 resultSet = entityInstancePKHolder; 473 } else { 474 resultSet.retainAll(entityInstancePKHolder); 475 } 476 } 477 478 if(emailAddress != null && (resultSet == null || resultSet.size() > 0)) { 479 EntityInstancePKHolder entityInstancePKHolder = getEntityInstancePKHolderByEmailAddress(emailAddress); 480 481 if(resultSet == null) { 482 resultSet = entityInstancePKHolder; 483 } else { 484 resultSet.retainAll(entityInstancePKHolder); 485 } 486 } 487 488 if(resultSet == null || resultSet.size() > 0) { 489 if(q != null) { 490 EntityInstancePKHolder entityInstancePKHolder = executeQuery(eea); 491 492 if(resultSet == null) { 493 resultSet = entityInstancePKHolder; 494 } else { 495 resultSet.retainAll(entityInstancePKHolder); 496 } 497 } 498 } 499 } else { 500 if(parameterCount == 1) { 501 var partyControl = Session.getModelController(PartyControl.class); 502 Party party = null; 503 504 if(alias != null) { 505 if(partyAliasType == null) { 506 partyAliasType = partyControl.getDefaultPartyAliasType(partyType); 507 } 508 509 if(partyAliasType != null) { 510 party = partyControl.getPartyByAlias(partyAliasType, alias); 511 } 512 } 513 514 if(partyName != null) { 515 party = partyControl.getPartyByName(partyName); 516 517 // If it isn't the PartyType we're looking for, toss the Party away. 518 if(!party.getLastDetail().getPartyType().equals(partyType)) { 519 party = null; 520 } 521 } 522 523 if(party != null) { 524 resultSet = new EntityInstancePKHolder(1); 525 resultSet.add(getCoreControl().getEntityInstanceByBasePK(party.getPrimaryKey()).getPrimaryKey(), null); 526 } 527 } 528 } 529 530 return resultSet; 531 } 532 533}