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.model.control.forum.server.search;
018
019import com.echothree.model.control.core.common.ComponentVendors;
020import com.echothree.model.control.core.common.EntityTypes;
021import com.echothree.model.control.forum.common.ForumConstants;
022import com.echothree.model.control.forum.server.analyzer.ForumMessageAnalyzer;
023import com.echothree.model.control.forum.server.control.ForumControl;
024import com.echothree.model.control.index.common.IndexConstants;
025import com.echothree.model.control.index.common.IndexFieldVariations;
026import com.echothree.model.control.index.common.IndexFields;
027import com.echothree.model.control.index.common.IndexTypes;
028import com.echothree.model.control.index.server.analyzer.BasicAnalyzer;
029import com.echothree.model.control.search.common.SearchSortDirections;
030import com.echothree.model.control.search.common.SearchSortOrders;
031import com.echothree.model.control.search.server.search.BaseSearchEvaluator;
032import com.echothree.model.control.search.server.search.EntityInstancePKHolder;
033import com.echothree.model.data.core.server.factory.EntityInstanceFactory;
034import com.echothree.model.data.forum.server.entity.Forum;
035import com.echothree.model.data.forum.server.entity.ForumMessageType;
036import com.echothree.model.data.party.server.entity.Language;
037import com.echothree.model.data.search.server.entity.SearchDefaultOperator;
038import com.echothree.model.data.search.server.entity.SearchSortDirection;
039import com.echothree.model.data.search.server.entity.SearchSortOrder;
040import com.echothree.model.data.search.server.entity.SearchType;
041import com.echothree.model.data.search.server.entity.SearchUseType;
042import com.echothree.model.data.user.server.entity.UserVisit;
043import com.echothree.util.server.message.ExecutionErrorAccumulator;
044import com.echothree.util.server.persistence.Session;
045import org.apache.lucene.search.SortField;
046
047public class ForumMessageSearchEvaluator
048        extends BaseSearchEvaluator {
049    
050    private Forum forum;
051    private ForumMessageType forumMessageType;
052    private boolean includeFutureForumThreads;
053    
054    /** Creates a new instance of ForumMessageSearchEvaluator */
055    public ForumMessageSearchEvaluator(UserVisit userVisit, Language language, SearchType searchType, SearchDefaultOperator searchDefaultOperator, SearchSortOrder searchSortOrder,
056            SearchSortDirection searchSortDirection, SearchUseType searchUseType, Forum forum, ForumMessageType forumMessageType) {
057        super(userVisit, searchDefaultOperator, searchType, searchSortOrder, searchSortDirection, searchUseType, ComponentVendors.ECHO_THREE.name(),
058                EntityTypes.ForumMessage.name(), IndexTypes.FORUM_MESSAGE.name(), language, null);
059        
060        this.forum = forum;
061        this.forumMessageType = forumMessageType;
062        
063        var forumControl = Session.getModelController(ForumControl.class);
064        var indexDefaultForumMessageTypePartType = forumControl.getIndexDefaultForumMessageTypePartType(forumMessageType);
065
066        setField(indexDefaultForumMessageTypePartType.getForumMessagePartType().getForumMessagePartTypeName());
067    }
068    
069    public EntityInstancePKHolder getEntityInstancePKHolderByForum(Forum forum) {
070        EntityInstancePKHolder entityInstancePKHolder;
071        var ps = EntityInstanceFactory.getInstance().prepareStatement(
072                "SELECT _PK_ " +
073                "FROM componentvendors, componentvendordetails, entitytypes, entitytypedetails, entityinstances, forummessages, forummessagedetails, forumforumthreads " +
074                "WHERE frmmsg_activedetailid = frmmsgdt_forummessagedetailid " +
075                "AND frmmsgdt_frmthrd_forumthreadid = frmfrmthrd_frmthrd_forumthreadid AND frmfrmthrd_thrutime = ? " +
076                "AND frmfrmthrd_frm_forumid = ? " +
077                "AND cvnd_activedetailid = cvndd_componentvendordetailid AND cvndd_componentvendorname = ? " +
078                "AND ent_activedetailid = entdt_entitytypedetailid " +
079                "AND cvnd_componentvendorid = entdt_cvnd_componentvendorid " +
080                "AND entdt_entitytypename = ? " +
081                "AND ent_entitytypeid = eni_ent_entitytypeid AND frmmsg_forummessageid = eni_entityuniqueid " +
082                (includeFutureForumThreads ? "" : "AND frmmsgdt_postedtime <= ?"));
083        
084        if(includeFutureForumThreads) {
085            entityInstancePKHolder = getEntityInstancePKHolderFromQuery(ps,
086                    Session.MAX_TIME, forum, ComponentVendors.ECHO_THREE.name(), EntityTypes.ForumMessage.name());
087        } else {
088            entityInstancePKHolder = getEntityInstancePKHolderFromQuery(ps,
089                    Session.MAX_TIME, forum, ComponentVendors.ECHO_THREE.name(), EntityTypes.ForumMessage.name(), session.START_TIME);
090        }
091
092        return entityInstancePKHolder;
093    }
094
095    public EntityInstancePKHolder getEntityInstancePKHolderByForumMessageType(ForumMessageType forumMessageType) {
096        EntityInstancePKHolder entityInstancePKHolder;
097        var ps = EntityInstanceFactory.getInstance().prepareStatement(
098                "SELECT _PK_ " +
099                "FROM componentvendors, componentvendordetails, entitytypes, entitytypedetails, entityinstances, forummessages, forummessagedetails " +
100                "WHERE frmmsg_activedetailid = frmmsgdt_forummessagedetailid " +
101                "AND frmmsgdt_frmmsgtyp_forummessagetypeid = ? " +
102                "AND cvnd_activedetailid = cvndd_componentvendordetailid AND cvndd_componentvendorname = ? " +
103                "AND ent_activedetailid = entdt_entitytypedetailid " +
104                "AND cvnd_componentvendorid = entdt_cvnd_componentvendorid " +
105                "AND entdt_entitytypename = ? " +
106                "AND ent_entitytypeid = eni_ent_entitytypeid AND frmmsg_forummessageid = eni_entityuniqueid " +
107                (includeFutureForumThreads ? "" : "AND frmmsgdt_postedtime <= ?"));
108
109        if(includeFutureForumThreads) {
110            entityInstancePKHolder = getEntityInstancePKHolderFromQuery(ps,
111                    forumMessageType, ComponentVendors.ECHO_THREE.name(), EntityTypes.ForumMessage.name());
112        } else {
113            entityInstancePKHolder = getEntityInstancePKHolderFromQuery(ps,
114                    forumMessageType, ComponentVendors.ECHO_THREE.name(), EntityTypes.ForumMessage.name(),  session.START_TIME);
115        }
116
117        return entityInstancePKHolder;
118    }
119
120    /**
121     * Returns the includeFutureForumThreads.
122     * @return the includeFutureForumThreads
123     */
124    public boolean isIncludeFutureForumThreads() {
125        return includeFutureForumThreads;
126    }
127
128    /**
129     * Sets the includeFutureForumThreads.
130     * @param includeFutureForumThreads the includeFutureForumThreads to set
131     */
132    public void setIncludeFutureForumThreads(boolean includeFutureForumThreads) {
133        this.includeFutureForumThreads = includeFutureForumThreads;
134    }
135
136    @Override
137    public SortField[] getSortFields(String searchSortOrderName) {
138        SortField[] sortFields = null;
139        var reverse = searchSortDirection.getLastDetail().getSearchSortDirectionName().equals(SearchSortDirections.DESCENDING.name());
140        
141        if(searchSortOrderName.equals(SearchSortOrders.SCORE.name())) {
142            sortFields = new SortField[]{
143                new SortField(null, SortField.Type.SCORE, reverse),
144                new SortField(ForumConstants.ForumMessagePartType_TITLE + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.sortable.name(), SortField.Type.STRING, reverse)
145            };
146        } else if(searchSortOrderName.equals(SearchSortOrders.TITLE.name())) {
147            sortFields = new SortField[]{new SortField(ForumConstants.ForumMessagePartType_TITLE + IndexConstants.INDEX_FIELD_VARIATION_SEPARATOR + IndexFieldVariations.sortable.name(), SortField.Type.STRING, reverse)};
148        } else if(searchSortOrderName.equals(SearchSortOrders.POSTED_TIME.name())) {
149            sortFields = new SortField[]{new SortField(IndexFields.postedTime.name(), SortField.Type.LONG, reverse)};
150        } else if(searchSortOrderName.equals(SearchSortOrders.CREATED_TIME.name())) {
151            sortFields = new SortField[]{new SortField(IndexFields.createdTime.name(), SortField.Type.LONG, reverse)};
152        } else if(searchSortOrderName.equals(SearchSortOrders.MODIFIED_TIME.name())) {
153            sortFields = new SortField[]{new SortField(IndexFields.modifiedTime.name(), SortField.Type.LONG, reverse)};
154        }
155        
156        return sortFields;
157    }
158    
159    @Override
160    public BasicAnalyzer getAnalyzer(final ExecutionErrorAccumulator eea, final Language language) {
161        return new ForumMessageAnalyzer(eea, language, entityType);
162    }
163    
164    @Override
165    protected EntityInstancePKHolder executeSearch(final ExecutionErrorAccumulator eea) {
166        var resultSet = super.executeSearch(eea);
167        
168        if(resultSet == null || resultSet.size() > 0) {
169            if(q != null) {
170                if(resultSet == null || resultSet.size() > 0) {
171                    var entityInstancePKHolder = executeQuery(eea);
172
173                    if(resultSet == null) {
174                        resultSet = entityInstancePKHolder;
175                    } else {
176                        resultSet.retainAll(entityInstancePKHolder);
177                    }
178                }
179            }
180        }
181
182        if(resultSet == null || resultSet.size() > 0) {
183            if(forum != null) {
184                var entityInstancePKHolder = getEntityInstancePKHolderByForum(forum);
185
186                if(resultSet == null) {
187                    resultSet = entityInstancePKHolder;
188                } else {
189                    resultSet.retainAll(entityInstancePKHolder);
190                }
191            }
192        }
193
194        if(resultSet == null || resultSet.size() > 0) {
195            if(forumMessageType != null) {
196                var entityInstancePKHolder = getEntityInstancePKHolderByForumMessageType(forumMessageType);
197
198                if(resultSet == null) {
199                    resultSet = entityInstancePKHolder;
200                } else {
201                    resultSet.retainAll(entityInstancePKHolder);
202                }
203            }
204        }
205
206        return resultSet;
207    }
208
209}