001// --------------------------------------------------------------------------------
002// Copyright 2002-2026 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.indexer;
018
019import com.echothree.model.control.index.common.IndexFields;
020import com.echothree.model.control.index.server.indexer.BaseIndexer;
021import com.echothree.model.control.index.server.indexer.FieldTypes;
022import com.echothree.model.control.party.server.analyzer.PartyAnalyzer;
023import com.echothree.model.control.party.server.control.PartyControl;
024import com.echothree.model.control.party.server.logic.PartyLogic;
025import com.echothree.model.data.core.server.entity.EntityInstance;
026import com.echothree.model.data.index.server.entity.Index;
027import com.echothree.model.data.party.server.entity.Party;
028import com.echothree.model.data.party.server.entity.PartyType;
029import com.echothree.util.server.message.ExecutionErrorAccumulator;
030import javax.inject.Inject;
031import org.apache.lucene.analysis.Analyzer;
032import org.apache.lucene.document.Document;
033import org.apache.lucene.document.Field;
034
035public abstract class PartyIndexer
036        extends BaseIndexer<Party> {
037
038    @Inject
039    PartyControl partyControl;
040    
041    protected PartyType partyType;
042    protected String entityNameIndexField;
043    
044    protected BaseIndexer<Party> setup(final ExecutionErrorAccumulator eea, final Index index, final String partyTypeName,
045            final String entityNameIndexField) {
046        this.partyType = PartyLogic.getInstance().getPartyTypeByName(eea, partyTypeName);
047        this.entityNameIndexField = entityNameIndexField;
048
049        return super.setup(eea, index);
050    }
051    
052    @Override
053    protected Party getEntity(final EntityInstance entityInstance) {
054        return partyControl.getPartyByEntityInstance(entityInstance);
055
056    }
057
058    @Override
059    protected Analyzer getAnalyzer() {
060        return new PartyAnalyzer(eea, language, entityType, entityAliasTypes, entityAttributes, tagScopes, partyType, entityNameIndexField);
061    }
062
063    /**
064     * All PartyTypes have their own EntityName in addition to the partyName. If null is returned for this field, it
065     * likely indicates that the Party has been deleted before indexing picked it up and it will be ignored.
066     * @param party Party to return the EntityName for
067     * @return String with the EntityName, or null if it was not found
068     */
069    protected abstract String getEntityNameFromParty(final Party party);
070
071    protected void addPartyFieldsToDocument(final Party party, final String entityName, final Document document) {
072        var partyDetail = party.getLastDetail();
073        var person = partyControl.getPerson(party);
074        var partyGroup = partyControl.getPartyGroup(party);
075        var name = partyGroup == null ? null : partyGroup.getName();
076        var partyAliases = partyControl.getPartyAliasesByParty(party);
077
078        document.add(new Field(IndexFields.partyName.name(), partyDetail.getPartyName(), FieldTypes.NOT_STORED_TOKENIZED));
079        document.add(new Field(entityNameIndexField, entityName, FieldTypes.NOT_STORED_TOKENIZED));
080
081        if(name != null) {
082            document.add(new Field(IndexFields.name.name(), name, FieldTypes.NOT_STORED_TOKENIZED));
083        }
084
085        if(person != null) {
086            var firstName = person.getFirstName();
087            var middleName = person.getMiddleName();
088            var lastName = person.getLastName();
089
090            if(firstName != null) {
091                document.add(new Field(IndexFields.firstName.name(), firstName, FieldTypes.NOT_STORED_TOKENIZED));
092            }
093            if(middleName != null) {
094                document.add(new Field(IndexFields.middleName.name(), middleName, FieldTypes.NOT_STORED_TOKENIZED));
095            }
096            if(lastName != null) {
097                document.add(new Field(IndexFields.lastName.name(), lastName, FieldTypes.NOT_STORED_TOKENIZED));
098            }
099        }
100
101        for(var partyAlias : partyAliases) {
102            document.add(new Field(partyAlias.getPartyAliasType().getLastDetail().getPartyAliasTypeName(),
103                    partyAlias.getAlias(), FieldTypes.NOT_STORED_TOKENIZED));
104        }
105    }
106
107    @Override
108    protected Document convertToDocument(final EntityInstance entityInstance, final Party party) {
109        var partyDetail = party.getLastDetail();
110        Document document = null;
111
112        if(partyDetail.getPartyType().equals(partyType)) {
113            var entityName = getEntityNameFromParty(party);
114
115            // If this field is null, do not index the Party.
116            if(entityName != null) {
117                document = newDocumentWithEntityInstanceFields(entityInstance, party.getPrimaryKey());
118
119                addPartyFieldsToDocument(party, entityName, document);
120            }
121        }
122
123        return document;
124    }
125
126}