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.search.server.logic; 018 019import com.echothree.model.control.core.server.control.EntityInstanceControl; 020import com.echothree.model.control.search.common.exception.DuplicateSearchResultActionException; 021import com.echothree.model.control.search.common.exception.UnknownCachedExecutedSearchResultException; 022import com.echothree.model.control.search.common.exception.UnknownDefaultSearchDefaultOperatorException; 023import com.echothree.model.control.search.common.exception.UnknownDefaultSearchSortDirectionException; 024import com.echothree.model.control.search.common.exception.UnknownDefaultSearchSortOrderException; 025import com.echothree.model.control.search.common.exception.UnknownSearchDefaultOperatorNameException; 026import com.echothree.model.control.search.common.exception.UnknownSearchKindNameException; 027import com.echothree.model.control.search.common.exception.UnknownSearchResultActionTypeNameException; 028import com.echothree.model.control.search.common.exception.UnknownSearchResultException; 029import com.echothree.model.control.search.common.exception.UnknownSearchSortDirectionNameException; 030import com.echothree.model.control.search.common.exception.UnknownSearchSortOrderNameException; 031import com.echothree.model.control.search.common.exception.UnknownSearchTypeNameException; 032import com.echothree.model.control.search.common.exception.UnknownSearchUseTypeNameException; 033import com.echothree.model.control.search.common.exception.UnknownUserVisitSearchException; 034import com.echothree.model.control.search.server.control.SearchControl; 035import com.echothree.model.control.search.server.database.CachedSearchToInvalidateQuery; 036import com.echothree.model.data.index.server.entity.Index; 037import com.echothree.model.data.search.server.entity.Search; 038import com.echothree.model.data.search.server.entity.SearchDefaultOperator; 039import com.echothree.model.data.search.server.entity.SearchKind; 040import com.echothree.model.data.search.server.entity.SearchResultAction; 041import com.echothree.model.data.search.server.entity.SearchResultActionType; 042import com.echothree.model.data.search.server.entity.SearchSortDirection; 043import com.echothree.model.data.search.server.entity.SearchSortOrder; 044import com.echothree.model.data.search.server.entity.SearchType; 045import com.echothree.model.data.search.server.entity.SearchUseType; 046import com.echothree.model.data.search.server.entity.UserVisitSearch; 047import com.echothree.model.data.user.server.entity.UserVisit; 048import com.echothree.util.common.message.ExecutionErrors; 049import com.echothree.util.common.persistence.BasePK; 050import com.echothree.util.server.control.BaseLogic; 051import com.echothree.util.server.message.ExecutionErrorAccumulator; 052import com.echothree.util.server.persistence.BaseEntity; 053import javax.enterprise.context.ApplicationScoped; 054import javax.enterprise.inject.spi.CDI; 055import javax.inject.Inject; 056 057@ApplicationScoped 058public class SearchLogic 059 extends BaseLogic { 060 061 @Inject 062 EntityInstanceControl entityInstanceControl; 063 064 @Inject 065 SearchControl searchControl; 066 067 protected SearchLogic() { 068 super(); 069 } 070 071 public static SearchLogic getInstance() { 072 return CDI.current().select(SearchLogic.class).get(); 073 } 074 075 public SearchDefaultOperator getSearchDefaultOperatorByName(final ExecutionErrorAccumulator eea, final String searchDefaultOperatorName) { 076 var searchDefaultOperator = searchControl.getSearchDefaultOperatorByName(searchDefaultOperatorName); 077 078 if(searchDefaultOperator == null) { 079 handleExecutionError(UnknownSearchDefaultOperatorNameException.class, eea, ExecutionErrors.UnknownSearchDefaultOperatorName.name(), searchDefaultOperatorName); 080 } 081 082 return searchDefaultOperator; 083 } 084 085 public SearchDefaultOperator getDefaultSearchDefaultOperator(final ExecutionErrorAccumulator eea) { 086 var searchDefaultOperator = searchControl.getDefaultSearchDefaultOperator(); 087 088 if(searchDefaultOperator == null) { 089 handleExecutionError(UnknownDefaultSearchDefaultOperatorException.class, eea, ExecutionErrors.UnknownDefaultSearchDefaultOperator.name()); 090 } 091 092 return searchDefaultOperator; 093 } 094 095 public SearchSortDirection getSearchSortDirectionByName(final ExecutionErrorAccumulator eea, final String searchSortDirectionName) { 096 var searchSortDirection = searchControl.getSearchSortDirectionByName(searchSortDirectionName); 097 098 if(searchSortDirection == null) { 099 handleExecutionError(UnknownSearchSortDirectionNameException.class, eea, ExecutionErrors.UnknownSearchSortDirectionName.name(), searchSortDirectionName); 100 } 101 102 return searchSortDirection; 103 } 104 105 public SearchSortDirection getDefaultSearchSortDirection(final ExecutionErrorAccumulator eea) { 106 var searchSortDirection = searchControl.getDefaultSearchSortDirection(); 107 108 if(searchSortDirection == null) { 109 handleExecutionError(UnknownDefaultSearchSortDirectionException.class, eea, ExecutionErrors.UnknownDefaultSearchSortDirection.name()); 110 } 111 112 return searchSortDirection; 113 } 114 115 public SearchUseType getSearchUseTypeByName(final ExecutionErrorAccumulator eea, final String searchUseTypeName) { 116 var searchUseType = searchControl.getSearchUseTypeByName(searchUseTypeName); 117 118 if(searchUseType == null) { 119 handleExecutionError(UnknownSearchUseTypeNameException.class, eea, ExecutionErrors.UnknownSearchUseTypeName.name(), searchUseTypeName); 120 } 121 122 return searchUseType; 123 } 124 125 public SearchResultActionType getSearchResultActionTypeByName(final ExecutionErrorAccumulator eea, final String searchResultActionTypeName) { 126 var searchResultActionType = searchControl.getSearchResultActionTypeByName(searchResultActionTypeName); 127 128 if(searchResultActionType == null) { 129 handleExecutionError(UnknownSearchResultActionTypeNameException.class, eea, ExecutionErrors.UnknownSearchResultActionTypeName.name(), searchResultActionTypeName); 130 } 131 132 return searchResultActionType; 133 } 134 135 public SearchKind getSearchKindByName(final ExecutionErrorAccumulator eea, final String searchKindName) { 136 var searchKind = searchControl.getSearchKindByName(searchKindName); 137 138 if(searchKind == null) { 139 handleExecutionError(UnknownSearchKindNameException.class, eea, ExecutionErrors.UnknownSearchKindName.name(), searchKindName); 140 } 141 142 return searchKind; 143 } 144 145 public SearchType getSearchTypeByName(final ExecutionErrorAccumulator eea, final SearchKind searchKind, final String searchTypeName) { 146 var searchType = searchControl.getSearchTypeByName(searchKind, searchTypeName); 147 148 if(searchType == null) { 149 handleExecutionError(UnknownSearchTypeNameException.class, eea, ExecutionErrors.UnknownSearchTypeName.name(), 150 searchKind.getLastDetail().getSearchKindName(), searchTypeName); 151 } 152 153 return searchType; 154 } 155 156 public SearchType getSearchTypeByName(final ExecutionErrorAccumulator eea, final String searchKindName, final String searchTypeName) { 157 var searchKind = getSearchKindByName(eea, searchKindName); 158 159 return hasExecutionErrors(eea) ? null : getSearchTypeByName(eea, searchKind, searchTypeName); 160 } 161 162 public SearchSortOrder getSearchSortOrderByName(final ExecutionErrorAccumulator eea, final SearchKind searchKind, final String searchSortOrderName) { 163 var searchSortOrder = searchControl.getSearchSortOrderByName(searchKind, searchSortOrderName); 164 165 if(searchSortOrder == null) { 166 handleExecutionError(UnknownSearchSortOrderNameException.class, eea, ExecutionErrors.UnknownSearchSortOrderName.name(), 167 searchKind.getLastDetail().getSearchKindName(), searchSortOrderName); 168 } 169 170 return searchSortOrder; 171 } 172 173 public SearchSortOrder getSearchSortOrderByName(final ExecutionErrorAccumulator eea, final String searchKindName, final String searchSortOrderName) { 174 var searchKind = getSearchKindByName(eea, searchKindName); 175 176 return hasExecutionErrors(eea) ? null : getSearchSortOrderByName(eea, searchKind, searchSortOrderName); 177 } 178 179 public SearchSortOrder getDefaultSearchSortOrder(final ExecutionErrorAccumulator eea, final SearchKind searchKind) { 180 var searchSortOrder = searchControl.getDefaultSearchSortOrder(searchKind); 181 182 if(searchSortOrder == null) { 183 handleExecutionError(UnknownDefaultSearchSortOrderException.class, eea, ExecutionErrors.UnknownDefaultSearchSortOrder.name(), 184 searchKind.getLastDetail().getSearchKindName()); 185 } 186 187 return searchSortOrder; 188 } 189 190 public SearchSortOrder getDefaultSearchSortOrder(final ExecutionErrorAccumulator eea, final String searchKindName) { 191 var searchKind = getSearchKindByName(eea, searchKindName); 192 193 return hasExecutionErrors(eea) ? null : getDefaultSearchSortOrder(eea, searchKind); 194 } 195 196 public UserVisitSearch getUserVisitSearch(final ExecutionErrorAccumulator eea, final UserVisit userVisit, final SearchType searchType) { 197 var userVisitSearch = searchControl.getUserVisitSearch(userVisit, searchType); 198 199 if(userVisitSearch == null) { 200 handleExecutionError(UnknownUserVisitSearchException.class, eea, ExecutionErrors.UnknownUserVisitSearch.name()); 201 } 202 203 return userVisitSearch; 204 } 205 206 public UserVisitSearch getUserVisitSearchByName(final ExecutionErrorAccumulator eea, final UserVisit userVisit, final String searchKindName, 207 final String searchTypeName) { 208 var searchType = getSearchTypeByName(eea, searchKindName, searchTypeName); 209 var userVisitSearch = hasExecutionErrors(eea) ? null : getUserVisitSearch(eea, userVisit, searchType); 210 211 return userVisitSearch; 212 } 213 214 public void removeUserVisitSearch(final ExecutionErrorAccumulator eea, final UserVisit userVisit, final String searchKindName, 215 final String searchTypeName) { 216 var userVisitSearch = getUserVisitSearchByName(eea, userVisit, searchKindName, searchTypeName); 217 218 if(!hasExecutionErrors(eea)) { 219 searchControl.removeUserVisitSearch(userVisitSearch); 220 } 221 } 222 223 public Long countSearchResults(final Search search) { 224 var cachedSearch = search.getCachedSearch(); 225 long count; 226 227 if(cachedSearch == null) { 228 count = searchControl.countSearchResults(search); 229 } else { 230 var cachedExecutedSearch = searchControl.getCachedExecutedSearch(cachedSearch); 231 232 count = searchControl.countCachedExecutedSearchResults(cachedExecutedSearch); 233 } 234 235 return count; 236 } 237 238 public Long countUserVisitSearchResults(final ExecutionErrorAccumulator eea, final UserVisit userVisit, final String searchKindName, 239 final String searchTypeName) { 240 var userVisitSearch = getUserVisitSearchByName(eea, userVisit, searchKindName, searchTypeName); 241 var count = hasExecutionErrors(eea) ? null : countSearchResults(userVisitSearch.getSearch()); 242 243 return count; 244 } 245 246 public SearchResultAction createSearchResultAction(final ExecutionErrorAccumulator eea, final UserVisit userVisit, final String searchKindName, 247 final String searchTypeName, final String searchResultActionTypeName, final BaseEntity baseEntity, final BasePK createdBy) { 248 SearchResultAction itemSearchResultAction = null; 249 var userVisitSearch = getUserVisitSearchByName(eea, userVisit, searchKindName, searchTypeName); 250 251 if(eea == null || !eea.hasExecutionErrors()) { 252 var searchResultActionType = getSearchResultActionTypeByName(eea, searchResultActionTypeName); 253 254 if(eea == null || !eea.hasExecutionErrors()) { 255 var search = userVisitSearch.getSearch(); 256 var cachedSearch = search.getCachedSearch(); 257 var basePK = baseEntity.getPrimaryKey(); 258 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(basePK); 259 260 if(cachedSearch == null) { 261 if(!searchControl.searchResultExists(search, entityInstance)) { 262 handleExecutionError(UnknownSearchResultException.class, eea, ExecutionErrors.UnknownSearchResult.name(), 263 searchKindName, searchTypeName, basePK.getEntityRef()); 264 } 265 } else { 266 var cachedExecutedSearch = searchControl.getCachedExecutedSearch(cachedSearch); 267 268 if(!searchControl.cachedExecutedSearchResultExists(cachedExecutedSearch, entityInstance)) { 269 handleExecutionError(UnknownCachedExecutedSearchResultException.class, eea, ExecutionErrors.UnknownCachedExecutedSearchResult.name(), 270 searchKindName, searchTypeName, basePK.getEntityRef()); 271 } 272 } 273 274 if(eea == null || !eea.hasExecutionErrors()) { 275 if(searchControl.searchResultActionExists(search, searchResultActionType, entityInstance)) { 276 handleExecutionError(DuplicateSearchResultActionException.class, eea, ExecutionErrors.DuplicateSearchResultAction.name(), 277 searchKindName, searchTypeName, searchResultActionTypeName, basePK.getEntityRef()); 278 } else { 279 searchControl.createSearchResultAction(search, searchResultActionType, getSession().getStartTime(), entityInstance, createdBy); 280 } 281 } 282 } 283 } 284 285 return itemSearchResultAction; 286 } 287 288 public void invalidateCachedSearchesByIndex(Index index) { 289 for(var cachedSearchToInvalidateResult : new CachedSearchToInvalidateQuery().execute(index)) { 290 cachedSearchToInvalidateResult.getCachedSearchStatus().setIsConsistent(false); 291 } 292 } 293 294}