package gov.nysenate.openleg.dao.notification; import com.google.common.eventbus.Subscribe; import gov.nysenate.openleg.client.view.notification.NotificationView; import gov.nysenate.openleg.dao.base.ElasticBaseDao; import gov.nysenate.openleg.dao.base.LimitOffset; import gov.nysenate.openleg.dao.base.SearchIndex; import gov.nysenate.openleg.model.notification.Notification; import gov.nysenate.openleg.model.notification.NotificationType; import gov.nysenate.openleg.model.notification.RegisteredNotification; import gov.nysenate.openleg.model.search.ClearIndexEvent; import gov.nysenate.openleg.model.search.RebuildIndexEvent; import gov.nysenate.openleg.model.search.SearchResults; import gov.nysenate.openleg.service.base.search.IndexedSearchService; import gov.nysenate.openleg.util.OutputUtils; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.sort.SortBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; import java.util.*; @Repository public class ElasticNotificationSearchDao extends ElasticBaseDao implements NotificationSearchDao, IndexedSearchService<RegisteredNotification> { Logger logger = LoggerFactory.getLogger(ElasticNotificationSearchDao.class); protected static final String notificationIndex = SearchIndex.NOTIFICATION.getIndexName(); protected static final String notificationType = "notifications"; protected static final String idType = "id"; protected static final String idId = "id"; /** --- Implemented Methods --- */ @Override public Optional<RegisteredNotification> getNotification(long notificationId) { return getRequest(notificationIndex, notificationType, Long.toString(notificationId), getResponse -> getNotificationFromSourceMap(getResponse.getSource())); } /** {@inheritDoc} */ @Override public SearchResults<RegisteredNotification> searchNotifications(QueryBuilder query, QueryBuilder filter, List<SortBuilder> sort, LimitOffset limitOffset) { // Restrict search to only notifications, excluding the id incrementer QueryBuilder fullFilter = QueryBuilders.boolQuery().filter(filter).must(QueryBuilders.typeQuery(notificationType)); SearchRequestBuilder request = getSearchRequest(notificationIndex, query, fullFilter, null, null, sort, limitOffset, true); SearchResponse response = request.execute().actionGet(); return getSearchResults(response, limitOffset, hit -> getNotificationFromSourceMap(hit.getSource())); } /** {@inheritDoc} */ @Override public RegisteredNotification registerNotification(Notification notification) { RegisteredNotification regNotification = new RegisteredNotification(notification, getNextId()); searchClient.prepareIndex(notificationIndex, notificationType, Long.toString(regNotification.getId())) .setSource(OutputUtils.toJson(new NotificationView(regNotification))) .execute().actionGet(); return regNotification; } /** {@inheritDoc} */ @Override protected List<String> getIndices() { return Collections.singletonList(notificationIndex); } /** {@inheritDoc} */ @Override public void updateIndex(RegisteredNotification content) {} /** {@inheritDoc} */ @Override public void updateIndex(Collection<RegisteredNotification> content) {} /** {@inheritDoc} */ @Override public void clearIndex() { purgeIndices(); } /** {@inheritDoc} */ @Override public void rebuildIndex() { clearIndex(); } /** {@inheritDoc} */ @Subscribe @Override public void handleRebuildEvent(RebuildIndexEvent event) { if (event.affects(SearchIndex.NOTIFICATION)) { rebuildIndex(); } } /** {@inheritDoc} */ @Override @Subscribe public void handleClearEvent(ClearIndexEvent event) { if (event.affects(SearchIndex.NOTIFICATION)) { clearIndex(); } } /** --- Internal Methods --- */ /** * Gets the next available notification id by indexing to id/id and returning the version from the response * @return long - the next available notification id */ protected long getNextId() { IndexResponse response = searchClient.prepareIndex(notificationIndex, idType, idId) .setSource("{}").execute().actionGet(); return response.getVersion(); } protected RegisteredNotification getNotificationFromSourceMap(Map<String, Object> source) { long id = Long.parseLong(source.get("id").toString()); NotificationType type = NotificationType.getValue(source.get("notificationType").toString()); LocalDateTime occurred = LocalDateTime.parse(source.get("occurred").toString()); String summary = source.get("summary") != null ? source.get("summary").toString() : ""; String message = source.get("message") != null ? source.get("message").toString() : ""; return new RegisteredNotification(id, type, occurred, summary, message); } }