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