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.contact.server.indexer; 018 019import com.echothree.model.control.contact.common.ContactMechanismTypes; 020import com.echothree.model.control.contact.server.control.ContactControl; 021import com.echothree.model.control.geo.server.control.GeoControl; 022import com.echothree.model.control.index.common.IndexConstants; 023import com.echothree.model.control.index.common.IndexFieldVariations; 024import com.echothree.model.control.index.common.IndexFields; 025import com.echothree.model.control.index.server.analysis.ContactMechanismAnalyzer; 026import com.echothree.model.control.index.server.indexer.BaseIndexer; 027import com.echothree.model.control.index.server.indexer.FieldTypes; 028import com.echothree.model.data.contact.server.entity.ContactEmailAddress; 029import com.echothree.model.data.contact.server.entity.ContactInet4Address; 030import com.echothree.model.data.contact.server.entity.ContactMechanism; 031import com.echothree.model.data.contact.server.entity.ContactMechanismDetail; 032import com.echothree.model.data.contact.server.entity.ContactMechanismPurpose; 033import com.echothree.model.data.contact.server.entity.ContactPostalAddress; 034import com.echothree.model.data.contact.server.entity.ContactTelephone; 035import com.echothree.model.data.contact.server.entity.ContactWebAddress; 036import com.echothree.model.data.contact.server.entity.PartyContactMechanismDetail; 037import com.echothree.model.data.core.server.entity.EntityInstance; 038import com.echothree.model.data.geo.server.entity.GeoCode; 039import com.echothree.model.data.index.server.entity.Index; 040import com.echothree.model.data.party.server.entity.Language; 041import com.echothree.model.data.party.server.entity.NameSuffix; 042import com.echothree.model.data.party.server.entity.Party; 043import com.echothree.model.data.party.server.entity.PartyType; 044import com.echothree.model.data.party.server.entity.PersonalTitle; 045import com.echothree.util.common.string.Inet4AddressUtils; 046import com.echothree.util.server.message.ExecutionErrorAccumulator; 047import com.echothree.util.server.persistence.Session; 048import java.util.HashSet; 049import java.util.Set; 050import org.apache.lucene.analysis.Analyzer; 051import org.apache.lucene.document.Document; 052import org.apache.lucene.document.Field; 053import org.apache.lucene.document.SortedDocValuesField; 054import org.apache.lucene.util.BytesRef; 055 056public class ContactMechanismIndexer 057 extends BaseIndexer<ContactMechanism> { 058 059 ContactControl contactControl = Session.getModelController(ContactControl.class); 060 GeoControl geoControl = Session.getModelController(GeoControl.class); 061 062 /** Creates a new instance of ContactMechanismIndexer */ 063 public ContactMechanismIndexer(final ExecutionErrorAccumulator eea, final Index index) { 064 super(eea, index); 065 } 066 067 @Override 068 protected Analyzer getAnalyzer() { 069 return new ContactMechanismAnalyzer(eea, language, entityType, entityAliasTypes, entityAttributes, tagScopes); 070 } 071 072 @Override 073 protected ContactMechanism getEntity(final EntityInstance entityInstance) { 074 return contactControl.getContactMechanismByEntityInstance(entityInstance); 075 } 076 077 private void addPartyNamesToDocument(Document document, Set<Party> parties) { 078 StringBuilder partyNamesBuilder = new StringBuilder(); 079 080 parties.forEach((party) -> { 081 if(partyNamesBuilder.length() != 0) { 082 partyNamesBuilder.append(' '); 083 } 084 085 partyNamesBuilder.append(party.getLastDetail().getPartyName()); 086 }); 087 088 document.add(new Field(IndexFields.partyNames.name(), partyNamesBuilder.toString(), FieldTypes.NOT_STORED_TOKENIZED)); 089 } 090 091 private void addPartyTypeNamesToDocument(Document document, Set<PartyType> partyTypes) { 092 StringBuilder partyTypeNamesBuilder = new StringBuilder(); 093 094 partyTypes.forEach((partyType) -> { 095 if(partyTypeNamesBuilder.length() != 0) { 096 partyTypeNamesBuilder.append(' '); 097 } 098 099 partyTypeNamesBuilder.append(partyType.getPartyTypeName()); 100 }); 101 102 document.add(new Field(IndexFields.partyTypeNames.name(), partyTypeNamesBuilder.toString(), FieldTypes.NOT_STORED_TOKENIZED)); 103 } 104 105 private void addContactMechanismPurposeNamesToDocument(Document document, Set<ContactMechanismPurpose> contactMechanismPurposes) { 106 StringBuilder contactMechanismPurposesNamesBuilder = new StringBuilder(); 107 108 contactMechanismPurposes.forEach((contactMechanismPurpose) -> { 109 if(contactMechanismPurposesNamesBuilder.length() != 0) { 110 contactMechanismPurposesNamesBuilder.append(' '); 111 } 112 113 contactMechanismPurposesNamesBuilder.append(contactMechanismPurpose.getContactMechanismPurposeName()); 114 }); 115 116 document.add(new Field(IndexFields.contactMechanismPurposeNames.name(), contactMechanismPurposesNamesBuilder.toString(), FieldTypes.NOT_STORED_TOKENIZED)); 117 } 118 119 private void addPartiesToDocument(final Document document, final ContactMechanism contactMechanism) { 120 Set<Party> parties = new HashSet<>(); 121 Set<PartyType> partyTypes = new HashSet<>(); 122 Set<ContactMechanismPurpose> contactMechanismPurposes = new HashSet<>(); 123 124 contactControl.getPartyContactMechanismsByContactMechanism(contactMechanism).stream().forEach((partyContactMechanism) -> { 125 PartyContactMechanismDetail partyContactMechanismDetail = partyContactMechanism.getLastDetail(); 126 Party party = partyContactMechanismDetail.getParty(); 127 parties.add(party); 128 partyTypes.add(party.getLastDetail().getPartyType()); 129 contactControl.getPartyContactMechanismPurposesByPartyContactMechanism(partyContactMechanism).stream().forEach((partyContactMechanismPurpose) -> { 130 contactMechanismPurposes.add(partyContactMechanismPurpose.getLastDetail().getContactMechanismPurpose()); 131 }); 132 }); 133 134 addPartyNamesToDocument(document, parties); 135 addPartyTypeNamesToDocument(document, partyTypes); 136 addContactMechanismPurposeNamesToDocument(document, contactMechanismPurposes); 137 } 138 139 private void addGeoCodeToDocument(final Document document, final Language language, final GeoCode geoCode, String description, final String geoCodeIndexField, final String descriptionIndexField) { 140 if(geoCode != null) { 141 description = geoControl.getBestGeoCodeDescription(geoCode, language); 142 143 document.add(new Field(geoCodeIndexField, geoCode.getLastDetail().getGeoCodeName(), FieldTypes.NOT_STORED_TOKENIZED)); 144 } 145 146 if(description != null) { 147 document.add(new Field(descriptionIndexField, description, FieldTypes.NOT_STORED_TOKENIZED)); 148 } 149 } 150 151 private void addContactEmailAddressToDocument(final Document document, final ContactMechanism contactMechanism) { 152 ContactEmailAddress contactEmailAddress = contactControl.getContactEmailAddress(contactMechanism); 153 154 if(contactEmailAddress != null) { 155 document.add(new Field(IndexFields.emailAddress.name(), contactEmailAddress.getEmailAddress(), FieldTypes.NOT_STORED_TOKENIZED)); 156 } 157 } 158 159 private void addContactInet4AddressToDocument(final Document document, final ContactMechanism contactMechanism) { 160 ContactInet4Address contactInet4Address = contactControl.getContactInet4Address(contactMechanism); 161 162 if(contactInet4Address != null) { 163 document.add(new Field(IndexFields.inet4Address.name(), Inet4AddressUtils.getInstance().formatInet4Address(contactInet4Address.getInet4Address()), FieldTypes.NOT_STORED_TOKENIZED)); 164 } 165 } 166 167 private void addContactPostalAddressToDocument(final Document document, final ContactMechanism contactMechanism, final Language language) { 168 ContactPostalAddress contactPostalAddress = contactControl.getContactPostalAddress(contactMechanism); 169 170 if(contactPostalAddress != null) { 171 PersonalTitle personalTitle = contactPostalAddress.getPersonalTitle(); 172 String firstName = contactPostalAddress.getFirstName(); 173 String middleName = contactPostalAddress.getMiddleName(); 174 String lastName = contactPostalAddress.getLastName(); 175 NameSuffix nameSuffix = contactPostalAddress.getNameSuffix(); 176 String companyName = contactPostalAddress.getCompanyName(); 177 String attention = contactPostalAddress.getAttention(); 178 String address2 = contactPostalAddress.getAddress2(); 179 String address3 = contactPostalAddress.getAddress3(); 180 181 if(personalTitle != null) { 182 document.add(new Field(IndexFields.personalTitle.name(), personalTitle.getLastDetail().getDescription(), FieldTypes.NOT_STORED_TOKENIZED)); 183 } 184 185 if(firstName != null) { 186 document.add(new Field(IndexFields.firstName.name(), firstName, FieldTypes.NOT_STORED_TOKENIZED)); 187 } 188 189 if(middleName != null) { 190 document.add(new Field(IndexFields.middleName.name(), middleName, FieldTypes.NOT_STORED_TOKENIZED)); 191 } 192 193 if(lastName != null) { 194 document.add(new Field(IndexFields.lastName.name(), lastName, FieldTypes.NOT_STORED_TOKENIZED)); 195 } 196 197 if(nameSuffix != null) { 198 document.add(new Field(IndexFields.nameSuffix.name(), nameSuffix.getLastDetail().getDescription(), FieldTypes.NOT_STORED_TOKENIZED)); 199 } 200 201 if(companyName != null) { 202 document.add(new Field(IndexFields.companyName.name(), companyName, FieldTypes.NOT_STORED_TOKENIZED)); 203 } 204 205 if(attention != null) { 206 document.add(new Field(IndexFields.attention.name(), attention, FieldTypes.NOT_STORED_TOKENIZED)); 207 } 208 209 document.add(new Field(IndexFields.address1.name(), contactPostalAddress.getAddress1(), FieldTypes.NOT_STORED_TOKENIZED)); 210 211 if(address2 != null) { 212 document.add(new Field(IndexFields.address2.name(), address2, FieldTypes.NOT_STORED_TOKENIZED)); 213 } 214 215 if(address3 != null) { 216 document.add(new Field(IndexFields.address3.name(), address3, FieldTypes.NOT_STORED_TOKENIZED)); 217 } 218 219 addGeoCodeToDocument(document, language, contactPostalAddress.getCityGeoCode(), contactPostalAddress.getCity(), IndexFields.cityGeoCodeName.name(), IndexFields.city.name()); 220 addGeoCodeToDocument(document, language, contactPostalAddress.getCountyGeoCode(), null, IndexFields.countyGeoCodeName.name(), IndexFields.county.name()); 221 addGeoCodeToDocument(document, language, contactPostalAddress.getStateGeoCode(), contactPostalAddress.getState(), IndexFields.stateGeoCodeName.name(), IndexFields.state.name()); 222 addGeoCodeToDocument(document, language, contactPostalAddress.getPostalCodeGeoCode(), contactPostalAddress.getPostalCode(), IndexFields.postalCodeGeoCodeName.name(), IndexFields.postalCode.name()); 223 addGeoCodeToDocument(document, language, contactPostalAddress.getCountryGeoCode(), null, IndexFields.countryGeoCodeName.name(), IndexFields.country.name()); 224 225 document.add(new Field(IndexFields.isCommercial.name(), contactPostalAddress.getIsCommercial().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 226 } 227 } 228 229 private void addContactTelephoneToDocument(final Document document, final ContactMechanism contactMechanism) { 230 ContactTelephone contactTelephone = contactControl.getContactTelephone(contactMechanism); 231 232 if(contactTelephone != null) { 233 String areaCode = contactTelephone.getAreaCode(); 234 String telephoneExtension = contactTelephone.getTelephoneExtension(); 235 236 document.add(new Field(IndexFields.countryGeoCodeName.name(), contactTelephone.getCountryGeoCode().getLastDetail().getGeoCodeName(), FieldTypes.NOT_STORED_TOKENIZED)); 237 238 if(areaCode != null) { 239 document.add(new Field(IndexFields.areaCode.name(), areaCode, FieldTypes.NOT_STORED_TOKENIZED)); 240 } 241 242 document.add(new Field(IndexFields.telephoneNumber.name(), contactTelephone.getTelephoneNumber(), FieldTypes.NOT_STORED_TOKENIZED)); 243 244 if(telephoneExtension != null) { 245 document.add(new Field(IndexFields.telephoneExtension.name(), telephoneExtension, FieldTypes.NOT_STORED_TOKENIZED)); 246 } 247 } 248 } 249 250 private void addContactWebAddressToDocument(final Document document, final ContactMechanism contactMechanism) { 251 ContactWebAddress contactWebAddress = contactControl.getContactWebAddress(contactMechanism); 252 253 if(contactWebAddress != null) { 254 document.add(new Field(IndexFields.url.name(), contactWebAddress.getUrl(), FieldTypes.NOT_STORED_TOKENIZED)); 255 } 256 } 257 258 private void addContactMechanismToDocument(final Document document, final ContactMechanism contactMechanism, final Language language) { 259 ContactMechanismDetail contactMechanismDetail = contactMechanism.getLastDetail(); 260 String contactMechanismTypeName = contactMechanismDetail.getContactMechanismType().getContactMechanismTypeName(); 261 262 document.add(new Field(IndexFields.contactMechanismName.name(), contactMechanismDetail.getContactMechanismName(), FieldTypes.NOT_STORED_TOKENIZED)); 263 document.add(new SortedDocValuesField(IndexFields.contactMechanismName.name() + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.sortable.name(), 264 new BytesRef(contactMechanismDetail.getContactMechanismName()))); 265 266 document.add(new Field(IndexFields.contactMechanismTypeName.name(), contactMechanismTypeName, FieldTypes.NOT_STORED_TOKENIZED)); 267 document.add(new Field(IndexFields.allowSolicitation.name(), contactMechanismDetail.getAllowSolicitation().toString(), FieldTypes.NOT_STORED_TOKENIZED)); 268 269 if(contactMechanismTypeName.equals(ContactMechanismTypes.EMAIL_ADDRESS.name())) { 270 addContactEmailAddressToDocument(document, contactMechanism); 271 } else if(contactMechanismTypeName.equals(ContactMechanismTypes.INET_4.name())) { 272 addContactInet4AddressToDocument(document, contactMechanism); 273 } else if(contactMechanismTypeName.equals(ContactMechanismTypes.INET_6.name())) { 274 // TODO 275 } else if(contactMechanismTypeName.equals(ContactMechanismTypes.POSTAL_ADDRESS.name())) { 276 addContactPostalAddressToDocument(document, contactMechanism, language); 277 } else if(contactMechanismTypeName.equals(ContactMechanismTypes.TELECOM_ADDRESS.name())) { 278 addContactTelephoneToDocument(document, contactMechanism); 279 } else if(contactMechanismTypeName.equals(ContactMechanismTypes.WEB_ADDRESS.name())) { 280 addContactWebAddressToDocument(document, contactMechanism); 281 } 282 } 283 284 @Override 285 protected Document convertToDocument(final EntityInstance entityInstance, final ContactMechanism contactMechanism) { 286 var document = newDocumentWithEntityInstanceFields(entityInstance, contactMechanism.getPrimaryKey()); 287 288 addPartiesToDocument(document, contactMechanism); 289 addContactMechanismToDocument(document, contactMechanism, language); 290 291 return document; 292 } 293 294}