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.datatypes;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.List;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlElement;
025import javax.xml.bind.annotation.XmlRootElement;
026import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
027
028import org.apache.commons.lang3.StringUtils;
029import org.apache.log4j.Logger;
030import org.apache.solr.client.solrj.beans.Field;
031
032import core.tut.pori.dao.SolrDAO;
033import core.tut.pori.users.UserIdentity;
034import core.tut.pori.utils.ISODateAdapter;
035import service.tut.pori.apilta.files.datatypes.FileDetails;
036import service.tut.pori.apilta.files.datatypes.FileDetailsList;
037
038/**
039 * a single alert
040 * 
041 */
042@XmlRootElement(name=Definitions.ELEMENT_ALERT)
043@XmlAccessorType(XmlAccessType.NONE)
044public class Alert {
045  private static final Logger LOGGER = Logger.getLogger(Alert.class);
046  @Field(Definitions.SOLR_FIELD_ALERT_GROUP_ID)
047  private List<Long> _alertGroupIds = null;
048  @Field(core.tut.pori.dao.SolrDAO.SOLR_FIELD_ID)
049  @XmlElement(name=Definitions.ELEMENT_ALERT_ID)
050  private String _alertId = null;
051  @Field(Definitions.SOLR_FIELD_ALERT_TYPE)
052  @XmlElement(name=Definitions.ELEMENT_ALERT_TYPE)
053  private String _alertType = null;
054  @Field(SolrDAO.SOLR_FIELD_CREATED)
055  @XmlJavaTypeAdapter(ISODateAdapter.class)
056  @XmlElement(name=Definitions.ELEMENT_CREATED_TIMESTAMP)
057  private Date _created = null;
058  @Field(Definitions.SOLR_FIELD_DESCRIPTION)
059  @XmlElement(name=Definitions.ELEMENT_DESCRIPTION)
060  private String _description = null;
061  @XmlElement(name=service.tut.pori.apilta.files.datatypes.Definitions.ELEMENT_FILE_DETAILS_LIST)
062  private FileDetailsList _files = null;
063  @XmlElement(name=Definitions.ELEMENT_LOCATION)
064  private Location _location = null;
065  @Field(Definitions.SOLR_FIELD_RANGE)
066  @XmlElement(name=Definitions.ELEMENT_RANGE)
067  private Integer _range = null;
068  @XmlElement(name=core.tut.pori.users.Definitions.ELEMENT_USER_IDENTITY)
069  private UserIdentity _userId = null;
070  @Field(Definitions.SOLR_FIELD_VALID)
071  @XmlJavaTypeAdapter(ISODateAdapter.class)
072  @XmlElement(name=Definitions.ELEMENT_VALID_TIMESTAMP)
073  private Date _validUntil = null;
074  
075  /**
076   * for sub-classing, use the static
077   * 
078   * @return true if the alert is valid
079   * @see #isValid(Alert)
080   */
081  protected boolean isValid() {
082    if(StringUtils.isBlank(_alertType)){
083      LOGGER.debug("Invalid alert type.");
084      return false;
085    }else if(!UserIdentity.isValid(_userId)){
086      LOGGER.debug("Invalid user for the alert.");
087      return false;
088    }else if(!Location.isValid(_location)){
089      LOGGER.debug("Invalid location.");
090      return false;
091    }else if(!FileDetailsList.isEmpty(_files) && !FileDetailsList.isValid(_files)){
092      LOGGER.debug("Invalid file details.");
093      return false;
094    }else if(_range != null && _range < 1){
095      LOGGER.debug("Invalid range.");
096      return false;
097    }
098    
099    if(_validUntil != null){
100      if(_created == null){
101        LOGGER.debug("Valid until timestamp was given, but no created.");
102        return false;
103      }else if(_validUntil.before(_created)){
104        LOGGER.debug("Valid until timestamp is before created timestamp.");
105        return false;
106      }
107    }
108    
109    return true;
110  }
111  
112  /**
113   * 
114   * @param alert
115   * @return false if the alert is null or invalid
116   */
117  public static boolean isValid(Alert alert) {
118    return (alert != null && alert.isValid());
119  }
120  
121  /**
122   * 
123   * @return created
124   * @see #setCreated(Date)
125   */
126  public Date getCreated() {
127    return _created;
128  }
129
130  /**
131   * 
132   * @param created
133   * @see #getCreated()
134   */
135  public void setCreated(Date created) {
136    _created = created;
137  }
138
139  /**
140   * @return the alertGroupIds
141   * @see #setAlertGroupIds(List)
142   */
143  public List<Long> getAlertGroupIds() {
144    return _alertGroupIds;
145  }
146  
147  /**
148   * @param alertGroupIds the alertGroupId to set
149   * @see #getAlertGroupIds()
150   */
151  public void setAlertGroupIds(List<Long> alertGroupIds) {
152    _alertGroupIds = alertGroupIds;
153  }
154  
155  /**
156   * @return the alertType
157   * @see #setAlertType(String)
158   */
159  public String getAlertType() {
160    return _alertType;
161  }
162  
163  /**
164   * @param alertType the alertType to set
165   * @see #getAlertType()
166   */
167  public void setAlertType(String alertType) {
168    _alertType = alertType;
169  }
170  
171  /**
172   * @return the description
173   * @see #setDescription(String)
174   */
175  public String getDescription() {
176    return _description;
177  }
178  
179  /**
180   * @param description the description to set
181   * @see #getDescription()
182   */
183  public void setDescription(String description) {
184    _description = description;
185  }
186  
187  /**
188   * @return the files
189   * @see #setFiles(FileDetailsList)
190   */
191  public FileDetailsList getFiles() {
192    return _files;
193  }
194  
195  /**
196   * @param files the files to set
197   * @see #getFiles()
198   */
199  public void setFiles(FileDetailsList files) {
200    _files = files;
201  }
202  
203  /**
204   * @return the location
205   * @see #setLocation(Location)
206   */
207  public Location getLocation() {
208    return _location;
209  }
210  
211  /**
212   * @param location the location to set
213   * @see #getLocation()
214   */
215  public void setLocation(Location location) {
216    _location = location;
217  }
218  
219  /**
220   * @return the userId
221   * @see #setUserId(UserIdentity)
222   */
223  public UserIdentity getUserId() {
224    return _userId;
225  }
226  
227  /**
228   * @param userId the userId to set
229   * @see #getUserId()
230   */
231  public void setUserId(UserIdentity userId) {
232    _userId = userId;
233  }
234  
235  /**
236   * for solr
237   * 
238   * @param userId
239   * @see #setUserId(UserIdentity)
240   */
241  @Field(Definitions.SOLR_FIELD_USER_ID)
242  private void setUserIdValue(Long userId){
243    _userId = (userId == null ? null : new UserIdentity(userId));
244  }
245  
246  /**
247   * for solr
248   * 
249   * @return user identity value
250   * @see #getUserId()
251   */
252  public Long getUserIdValue(){
253    return (_userId == null ? null : _userId.getUserId());
254  }
255  
256  /**
257   * for solr
258   * 
259   * @param fileGUIDs
260   * @see #setFiles(FileDetailsList)
261   */
262  @Field(Definitions.SOLR_FIELD_FILE_GUIDS)
263  private void setFileGUIDs(List<String> fileGUIDs) {
264    if(fileGUIDs == null || fileGUIDs.isEmpty()){
265      _files = null;
266      return;
267    }
268    ArrayList<FileDetails> details = new ArrayList<>(fileGUIDs.size());
269    for(String guid : fileGUIDs){
270      FileDetails d = new FileDetails();
271      d.setGUID(guid);
272      details.add(d);
273    }
274    _files = new FileDetailsList();
275    _files.setFiles(details);
276  }
277  
278  /**
279   * for solr
280   * 
281   * @return lists of file GUIDs or null if no files
282   * @see #getFiles()
283   */
284  public List<String> getFileGUIDs() {
285    if(FileDetailsList.isEmpty(_files)){
286      return null;
287    }else{
288      List<FileDetails> details = _files.getFiles();
289      ArrayList<String> guids = new ArrayList<>(details.size());
290      for(FileDetails d : details){
291        guids.add(d.getGUID());
292      }
293      return guids;
294    }
295  }
296  
297  /**
298   * for solr
299   * 
300   * @param location
301   * @see #setLocation(Location)
302   */
303  @Field(Definitions.SOLR_FIELD_LOCATION)
304  private void setLocationString(String location) {
305    if(StringUtils.isBlank(location)){
306      _location = null;
307    }else{
308      _location = new Location();
309      String[] parts = StringUtils.split(location);
310      _location.setLongitude(Double.valueOf(parts[0]));
311      _location.setLatitude(Double.valueOf(parts[1]));
312    }
313  }
314  
315  /**
316   * for solr
317   * 
318   * @return location as a string
319   * @see #getLocation()
320   */
321  public String getLocationString() {
322    if(Location.isValid(_location)){
323      return _location.getLongitude().toString()+' '+_location.getLatitude().toString();
324    }else{
325      return null;
326    }
327  }
328  
329  /**
330   * 
331   * @return the Solr database id
332   * @see #setAlertId(String)
333   */
334  public String getAlertId() {
335    return _alertId;
336  }
337  
338  /**
339   * 
340   * @param id
341   * @see #getAlertId()
342   */
343  public void setAlertId(String id) {
344    _alertId = id;
345  }
346
347  /**
348   * @return the validUntil
349   * @see #setValidUntil(Date)
350   */
351  public Date getValidUntil() {
352    return _validUntil;
353  }
354
355  /**
356   * @param validUntil the validUntil to set
357   * @see #getValidUntil()
358   */
359  public void setValidUntil(Date validUntil) {
360    _validUntil = validUntil;
361  }
362
363  /**
364   * @return the range this alert is valid from the center coordinate (in meters)
365   * @see #setRange(Integer)
366   */
367  public Integer getRange() {
368    return _range;
369  }
370
371  /**
372   * Note: this is not used when calculating range queries, this is an optional field that can be specified to give more information about the alert
373   * 
374   * @param range the range this alert is valid from the center coordinate (in meters)
375   * @see #getRange()
376   */
377  public void setRange(Integer range) {
378    _range = range;
379  }
380}