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