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}