/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
* Copyright (C) 2011 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.presentation.impl.service_alerts;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.onebusaway.collections.CollectionsLibrary;
import org.onebusaway.transit_data.model.service_alerts.ESeverity;
import org.onebusaway.transit_data.model.service_alerts.NaturalLanguageStringBean;
import org.onebusaway.transit_data.model.service_alerts.SituationAffectsBean;
import org.onebusaway.transit_data.model.service_alerts.ServiceAlertBean;
import org.onebusaway.transit_data.model.service_alerts.TimeRangeBean;
import org.onebusaway.users.client.model.UserBean;
public class SituationsPresentation {
private static RecentSituationComparator _comparator = new RecentSituationComparator();
private List<ServiceAlertBean> _situations;
private UserBean _user;
private long _time = System.currentTimeMillis();
private long _redisplayIfNowActiveThhreshold = 24 * 60 * 60 * 1000;
private String _apiKey = "web";
public void setApiKey(String apiKey) {
_apiKey = apiKey;
}
public String getApiKey() {
return _apiKey;
}
public void setSituations(List<ServiceAlertBean> situations) {
_situations = determineApplicationSituations(situations);
}
public void setUser(UserBean user) {
_user = user;
}
public void setRedisplayIfNowActiveThreshold(
long redisplayIfNowActiveThhreshold) {
_redisplayIfNowActiveThhreshold = redisplayIfNowActiveThhreshold;
}
public int getTotalCount() {
return _situations.size();
}
public int getUnreadCount() {
int unreadServiceAlertCount = 0;
Map<String, Long> readServiceAlerts = _user.getReadServiceAlerts();
for (ServiceAlertBean situation : _situations) {
if (isSituationUnread(readServiceAlerts, situation))
unreadServiceAlertCount++;
}
return unreadServiceAlertCount;
}
public String getUnreadServiceAlertsClass() {
ESeverity severity = getHighestUnreadSeverity();
if (severity == ESeverity.NO_IMPACT)
return "unreadServiceAlertsNoImpactSeverity";
return "unreadServiceAlertsNormalSeverity";
}
public List<ServiceAlertBean> getUnreadSituations() {
List<ServiceAlertBean> situations = new ArrayList<ServiceAlertBean>();
Map<String, Long> readServiceAlerts = _user.getReadServiceAlerts();
for (ServiceAlertBean situation : _situations) {
if (isSituationUnread(readServiceAlerts, situation))
situations.add(situation);
}
Collections.sort(situations, _comparator);
return situations;
}
public List<ServiceAlertBean> getReadSituations() {
List<ServiceAlertBean> situations = new ArrayList<ServiceAlertBean>();
Map<String, Long> readServiceAlerts = _user.getReadServiceAlerts();
for (ServiceAlertBean situation : _situations) {
if (readServiceAlerts.containsKey(situation.getId()))
situations.add(situation);
}
Collections.sort(situations, _comparator);
return situations;
}
public String getTitle(ServiceAlertBean situation) {
/**
* TODO: Better handling around language selection
*/
if (!CollectionsLibrary.isEmpty(situation.getSummaries()))
return getValue(situation.getSummaries().get(0));
if (!CollectionsLibrary.isEmpty(situation.getDescriptions()))
return getValue(situation.getDescriptions().get(0));
return null;
}
/****
* Private Methods
****/
public boolean isSet(NaturalLanguageStringBean bean) {
return bean != null && bean.getValue() != null
&& !bean.getValue().trim().isEmpty();
}
private String getValue(NaturalLanguageStringBean nls) {
String value = nls.getValue();
return value;
}
private boolean isSituationUnread(Map<String, Long> readServiceAlerts,
ServiceAlertBean situation) {
if (!isSituationInActivePublicationWindow(situation))
return false;
Long readTime = readServiceAlerts.get(situation.getId());
if (readTime == null)
return true;
/**
* Optionally, if a service alert has just become active and it hasn't been
* read in a while, we might also consider it unread.
*/
if (readTime + _redisplayIfNowActiveThhreshold < _time) {
if (!isSituationActiveAtTime(situation, readTime)
&& isSituationActiveAtTime(situation, _time))
return true;
}
return false;
}
private boolean isSituationInActivePublicationWindow(ServiceAlertBean situation) {
if (CollectionsLibrary.isEmpty(situation.getPublicationWindows()))
return true;
for (TimeRangeBean window : situation.getPublicationWindows()) {
if (isTimeRangeActive(window, _time, true))
return true;
}
return false;
}
private boolean isSituationActiveAtTime(ServiceAlertBean situation, long time) {
if (CollectionsLibrary.isEmpty(situation.getActiveWindows()))
return true;
for (TimeRangeBean window : situation.getActiveWindows()) {
if (isTimeRangeActive(window, _time, true))
return true;
}
return false;
}
private boolean isTimeRangeActive(TimeRangeBean window, long time,
boolean defaultOnUnspecified) {
/**
* If no publication window is specified, we assume it's always active
*/
if (window == null)
return defaultOnUnspecified;
long from = window.getFrom();
long to = window.getTo();
/**
* Again, if no publication window is specified, we assume it's always
* active
*/
if (from == 0 && to == 0)
return defaultOnUnspecified;
if (from == 0 && _time <= to)
return true;
if (to == 0 && from <= _time)
return true;
return (from <= _time && _time <= to);
}
private ESeverity getHighestUnreadSeverity() {
ESeverity maxSeverity = null;
Map<String, Long> readServiceAlerts = _user.getReadServiceAlerts();
for (ServiceAlertBean situation : _situations) {
if (isSituationUnread(readServiceAlerts, situation)) {
ESeverity s = situation.getSeverity();
if (s == null)
s = ESeverity.UNDEFINED;
if (maxSeverity == null
|| maxSeverity.getNumericValue() < s.getNumericValue())
maxSeverity = s;
}
}
return maxSeverity;
}
private List<ServiceAlertBean> determineApplicationSituations(
List<ServiceAlertBean> situations) {
List<ServiceAlertBean> applicable = new ArrayList<ServiceAlertBean>();
for (ServiceAlertBean situation : situations) {
if (isSituationApplicable(situation))
applicable.add(situation);
}
return applicable;
}
private boolean isSituationApplicable(ServiceAlertBean situation) {
Set<String> applicationIds = new HashSet<String>();
for (SituationAffectsBean affects : situation.getAllAffects()) {
if (affects.getApplicationId() != null)
applicationIds.add(affects.getApplicationId());
}
if (CollectionsLibrary.isEmpty(applicationIds))
return true;
if (_apiKey == null)
return false;
return applicationIds.contains(_apiKey);
}
}