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