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.io.InputStream; 019import java.util.ArrayList; 020import java.util.Date; 021import java.util.List; 022import java.util.Set; 023 024import org.apache.commons.lang3.ArrayUtils; 025import org.apache.log4j.Logger; 026 027import core.tut.pori.context.ServiceInitializer; 028import core.tut.pori.http.parameters.DataGroups; 029import core.tut.pori.http.parameters.DateIntervalParameter.Interval; 030import core.tut.pori.http.parameters.Limits; 031import core.tut.pori.users.UserIdentity; 032import core.tut.pori.utils.ListUtils; 033import service.tut.pori.apilta.ApiltaProperties; 034import service.tut.pori.apilta.alerts.datatypes.Alert; 035import service.tut.pori.apilta.alerts.datatypes.AlertList; 036import service.tut.pori.apilta.alerts.datatypes.AlertUserIdentity.UserPermission; 037import service.tut.pori.apilta.alerts.datatypes.Location; 038import service.tut.pori.apilta.alerts.datatypes.LocationParameter; 039import service.tut.pori.apilta.files.FilesCore; 040import service.tut.pori.apilta.files.datatypes.FileDetails; 041import service.tut.pori.apilta.files.datatypes.FileDetailsList; 042 043/** 044 * 045 * core methods for alerts service 046 */ 047public final class AlertsCore { 048 private static final Logger LOGGER = Logger.getLogger(AlertsCore.class); 049 050 /** 051 * 052 */ 053 private AlertsCore() { 054 // nothing needed 055 } 056 057 /** 058 * 059 * @param alertGroupIdFilter 060 * @param alertTypeFilter 061 * @param authenticatedUser 062 * @param createdFilter 063 * @param dataGroups 064 * @param limits 065 * @param location 066 * @param range 067 * @return list of alerts or null if none was found 068 */ 069 public static AlertList retrieveAlerts(long[] alertGroupIdFilter, List<String> alertTypeFilter, UserIdentity authenticatedUser, Set<Interval> createdFilter, DataGroups dataGroups, Limits limits, Location location, Double range) { 070 if(!Location.isValid(location)){ 071 if(ArrayUtils.isEmpty(alertGroupIdFilter)){ 072 throw new IllegalArgumentException(LocationParameter.PARAMETER_DEFAULT_NAME+" or "+Definitions.PARAMETER_ALERT_GROUP_ID+" must be given."); 073 }else if(range != null){ 074 throw new IllegalArgumentException(Definitions.PARAMETER_RANGE+" cannot be given without "+LocationParameter.PARAMETER_DEFAULT_NAME); 075 } 076 }else if(range == null){ 077 LOGGER.debug("Using default range: "+Definitions.DEFAULT_RANGE); 078 range = Definitions.DEFAULT_RANGE; 079 }else if(range <= 0){ 080 throw new IllegalArgumentException("Invalid range: "+range); 081 } 082 083 List<Long> validGroupIds = ServiceInitializer.getDAOHandler().getDAO(AlertGroupsDAO.class).getAlertGroupIds(alertGroupIdFilter, UserPermission.READ_ALERTS, authenticatedUser); 084 if(validGroupIds == null){ 085 LOGGER.debug("No valid alert groups for user, id: "+authenticatedUser.getUserId()); 086 return null; 087 } 088 089 AlertList alertList = ServiceInitializer.getDAOHandler().getDAO(AlertsDAO.class).getAlerts(validGroupIds, alertTypeFilter, createdFilter, dataGroups, limits, location, range); 090 if(!AlertList.isEmpty(alertList)){ 091 for(Alert alert : alertList.getAlerts()){ 092 FileDetailsList fileDetailsList = alert.getFiles(); 093 if(!FileDetailsList.isEmpty(fileDetailsList)){ // alert has file details 094 List<FileDetails> GUIDList = fileDetailsList.getFiles(); // the basic list only contains GUIDs 095 ArrayList<FileDetails> resolved = new ArrayList<>(GUIDList.size()); 096 for(FileDetails GUIDDetails : GUIDList){ // resolve file details 097 String guid = GUIDDetails.getGUID(); 098 FileDetails resolvedDetails = FilesCore.getFileDetails(guid); 099 if(resolvedDetails == null){ 100 LOGGER.warn("Could not resovle details for file, GUID: "+guid); 101 }else{ 102 resolved.add(resolvedDetails); 103 } 104 } 105 fileDetailsList.setFiles((resolved.isEmpty() ? null : resolved)); // replace the original list 106 } 107 } 108 } 109 110 return alertList; 111 } 112 113 /** 114 * 115 * @param alert 116 * @param alertGroupIds 117 * @param authenticatedUser 118 * @return identifier for the added alert or null on failure (permission denied) 119 * @throws IllegalArgumentException on bad input data 120 */ 121 public static String addAlert(Alert alert, long[] alertGroupIds, UserIdentity authenticatedUser) throws IllegalArgumentException { 122 if(ArrayUtils.isEmpty(alertGroupIds)){ 123 throw new IllegalArgumentException("Invalid or missing alert group ids."); 124 } 125 alert.setUserId(authenticatedUser); // make sure the authenticated user is the owner of this alert 126 if(!Alert.isValid(alert)){ 127 throw new IllegalArgumentException("Invalid alert."); 128 } 129 130 List<Long> validGroupIds = ServiceInitializer.getDAOHandler().getDAO(AlertGroupsDAO.class).getAlertGroupIds(alertGroupIds, UserPermission.POST_ALERT, authenticatedUser); 131 if(!ListUtils.containsAll(validGroupIds, alertGroupIds)){ 132 LOGGER.warn("User, id: "+authenticatedUser.getUserId()+" attempted to post alert to invaliding alert group id."); 133 return null; 134 } 135 136 Date created = alert.getCreated(); 137 if(created == null){ 138 LOGGER.debug("No created date, using current timestamp."); 139 created = new Date(); 140 alert.setCreated(created); 141 } 142 143 if(alert.getValidUntil() == null){ //TODO check from database if a specific validity time is available for the alert, also, create the database tables 144 alert.setValidUntil(new Date(created.getTime()+ServiceInitializer.getPropertyHandler().getSystemProperties(ApiltaProperties.class).getAlertValidityTime()*60000)); 145 } 146 147 return ServiceInitializer.getDAOHandler().getDAO(AlertsDAO.class).addAlert(alert, validGroupIds); // use valid group ids list to remove possible duplicates in the id list 148 } 149 150 /** 151 * 152 * @param file 153 * @return details for the created file or null on failure (permission denied) 154 * @throws IllegalArgumentException on bad data 155 */ 156 public static FileDetails createFile(InputStream file) throws IllegalArgumentException { 157 FileDetails details = FilesCore.createFile(file); 158 if(!FileDetails.isValid(details)){ 159 throw new IllegalArgumentException("Failed to create file from the given data."); 160 } 161 162 return details; 163 } 164 165 //TODO "floating" rating system for alerts? possibility to confirm/reject an existing alert? (implement on web page? do not allow on the mobile app?) 166 // i.e. "alert feedback", also allow users to remove their own alerts directly? 167}