001/**
002 * Copyright 2016 Tampere University of Technology, Pori Department
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 */
016package service.tut.pori.apilta.alerts;
017
018import java.util.Date;
019import java.util.List;
020import java.util.Set;
021import java.util.UUID;
022
023import org.apache.log4j.Logger;
024import org.apache.solr.common.SolrException;
025
026import core.tut.pori.dao.SQLSelectBuilder.OrderDirection;
027import core.tut.pori.dao.SolrDAO;
028import core.tut.pori.dao.SolrQueryBuilder;
029import core.tut.pori.dao.filter.AbstractQueryFilter.QueryType;
030import core.tut.pori.dao.filter.AndQueryFilter;
031import core.tut.pori.dao.filter.AndSubQueryFilter;
032import core.tut.pori.dao.filter.RangeQueryFilter;
033import core.tut.pori.http.parameters.DataGroups;
034import core.tut.pori.http.parameters.DateIntervalParameter.Interval;
035import core.tut.pori.http.parameters.Limits;
036import core.tut.pori.http.parameters.SortOptions;
037import service.tut.pori.apilta.alerts.datatypes.Alert;
038import service.tut.pori.apilta.alerts.datatypes.AlertList;
039import service.tut.pori.apilta.alerts.datatypes.AndGeoFilter;
040import service.tut.pori.apilta.alerts.datatypes.Definitions;
041import service.tut.pori.apilta.alerts.datatypes.Location;
042
043/**
044 * dao for accessing alert data
045 * 
046 */
047public class AlertsDAO extends SolrDAO {
048  private static final SortOptions DEFAULT_SORT_OPTIONS;
049  static{
050    DEFAULT_SORT_OPTIONS = new SortOptions();
051    DEFAULT_SORT_OPTIONS.addSortOption(new SortOptions.Option(SOLR_FIELD_ID, OrderDirection.ASCENDING, null));
052  }
053  private static final Logger LOGGER = Logger.getLogger(AlertsDAO.class);
054  private static final String[] SOLR_FIELDS_BASIC = {SOLR_FIELD_ID, Definitions.SOLR_FIELD_ALERT_TYPE, SOLR_FIELD_CREATED, Definitions.SOLR_FIELD_DESCRIPTION, Definitions.SOLR_FIELD_LOCATION};
055  private static final String SOLR_SERVER_BEAN_ID = "solrServerAlerts";
056
057  /**
058   * 
059   * @param alertGroupIdFilter optional filter
060   * @param alertTypeFilter optional filter
061   * @param createdFilter 
062   * @param dataGroups 
063   * @param limits
064   * @param location
065   * @param range
066   * @return list of alerts or null if none was found
067   */
068  public AlertList getAlerts(List<Long> alertGroupIdFilter, List<String> alertTypeFilter, Set<Interval> createdFilter, DataGroups dataGroups, Limits limits, Location location, Double range) {
069    SolrQueryBuilder solr = new SolrQueryBuilder();
070    solr.setLimits(limits);
071    solr.setSortOptions(DEFAULT_SORT_OPTIONS);
072            
073    if(!DataGroups.hasDataGroup(DataGroups.DATA_GROUP_ALL, dataGroups)){ // if all not present...
074      solr.addFields(SOLR_FIELDS_BASIC); // ... limit to basic details
075    }
076    
077    if(alertGroupIdFilter != null && !alertGroupIdFilter.isEmpty()){
078      LOGGER.debug("Using alert group id filter...");
079      solr.addCustomFilter(new AndQueryFilter(Definitions.SOLR_FIELD_ALERT_GROUP_ID, alertGroupIdFilter));
080    }
081    
082    if(alertTypeFilter != null && !alertTypeFilter.isEmpty()){
083      LOGGER.debug("Using alert type filter...");
084      solr.addCustomFilter(new AndQueryFilter(Definitions.SOLR_FIELD_ALERT_TYPE, alertTypeFilter));
085    }
086    
087    if(location != null){
088      LOGGER.debug("Using location filter..."); 
089      Double heading = location.getHeading();
090      if(heading != null){
091        LOGGER.warn("Ignored heading..."); // TODO calculate new bounding box/location based on heading ?
092      }
093      
094      solr.addCustomFilter(new AndGeoFilter(Definitions.SOLR_FIELD_LOCATION, location, range));
095    }
096    
097    if(createdFilter != null && !createdFilter.isEmpty()){
098      LOGGER.debug("Using created filter...");
099      AndSubQueryFilter cf = new AndSubQueryFilter();
100      for(Interval interval : createdFilter){
101        cf.addFilter(new RangeQueryFilter(SolrDAO.SOLR_FIELD_CREATED, interval.getStart(), interval.getEnd(), QueryType.OR));
102      }
103      solr.addCustomFilter(cf);
104    }
105    
106    solr.addCustomFilter(new RangeQueryFilter(Definitions.SOLR_FIELD_VALID, new Date(), null, QueryType.AND)); // check that the valid until timestamp is in the future (after current time)
107    
108    List<Alert> alerts = getSolrTemplate(SOLR_SERVER_BEAN_ID).queryForList(solr.toSolrQuery(Definitions.ELEMENT_ALERT_LIST), Alert.class);
109    if(alerts == null){
110      return null;
111    }else{
112      AlertList list = new AlertList();
113      list.setAlerts(alerts);
114      return list;
115    }
116  }
117
118  /**
119   * 
120   * @param alert
121   * @param alertGroupIds 
122   * @return id for the alert
123   */
124  public String addAlert(Alert alert, List<Long> alertGroupIds) {
125    String alertId = UUID.randomUUID().toString();
126    alert.setAlertId(alertId);
127    alert.setAlertGroupIds(alertGroupIds);
128      
129    int status = getSolrTemplate(SOLR_SERVER_BEAN_ID).addBean(alert).getStatus();
130    if(status != SolrException.ErrorCode.UNKNOWN.code){
131      LOGGER.warn("Failed to add alert, status: "+status);
132      alert.setAlertId(null);
133      return null;
134    }else{
135      return alertId;
136    }
137  }
138}