package com.schneeloch.bostonbusmap_library.data;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* Info about predictions and snippets.
* Separate from StopLocation because most StopLocations won't need to instantiate this
* Modification functions should be thread safe. Only predictionView should be published, because
* it's immutable
* @author schneg
*
*/
public class Predictions
{
@IsGuardedBy("modificationLock")
private PredictionView predictionView = StopPredictionViewImpl.empty();
@IsGuardedBy("modificationLock")
private final Set<String> routes = Sets.newHashSet();
/**
* A list of all stops that use this predictions list
*/
@IsGuardedBy("modificationLock")
private final List<StopLocation> allStops = Lists.newArrayList();
@IsGuardedBy("modificationLock")
private final SortedSet<IPrediction> predictions = Sets.newTreeSet();
private final Object modificationLock = new Object();
public void makeSnippetAndTitle(RouteConfig routeConfig,
RouteTitles routeKeysToTitles,
RouteSet routes, StopLocation stop, ImmutableCollection<Alert> alerts, Locations locations)
{
synchronized (modificationLock) {
this.routes.clear();
this.routes.addAll(routes.getRoutes());
allStops.clear();
allStops.add(stop);
Set<Alert> alertSet = Sets.newTreeSet(alerts);
ImmutableList<Alert> alertImmutableSet = ImmutableList.copyOf(alertSet);
predictionView = new StopPredictionViewImpl(this.routes, allStops,
predictions,
routeConfig, routeKeysToTitles, alertImmutableSet, locations);
}
}
public void addToSnippetAndTitle(RouteConfig routeConfig, StopLocation stopLocation,
RouteTitles routeKeysToTitles,
RouteSet routes, ImmutableCollection<Alert> alerts, Locations locations)
{
synchronized (modificationLock) {
allStops.add(stopLocation);
SortedSet<IPrediction> allPredictions = Sets.newTreeSet();
for (StopLocation stop : allStops) {
if (stop.getPredictions() != null) {
allPredictions.addAll(stop.getPredictions().predictions);
}
}
this.routes.addAll(routes.getRoutes());
Set<Alert> newAlerts;
if (alerts.size() == 0) {
newAlerts = Sets.newTreeSet(predictionView.getAlerts());
}
else
{
SortedSet<Alert> dupAlerts = Sets.newTreeSet();
dupAlerts.addAll(predictionView.getAlerts());
dupAlerts.addAll(alerts);
newAlerts = dupAlerts;
}
ImmutableSet.Builder<Alert> immutableNewAlerts = ImmutableSet.builder();
immutableNewAlerts.addAll(newAlerts);
predictionView = new StopPredictionViewImpl(this.routes, allStops,
allPredictions,
routeConfig,
routeKeysToTitles, immutableNewAlerts.build(),
locations);
}
}
/**
* Clear all predictions for a single route
* @param currentRouteName
*/
public void clearPredictions(String currentRouteName)
{
synchronized (modificationLock) {
if (currentRouteName != null) {
ArrayList<IPrediction> newPredictions = Lists.newArrayList();
for (IPrediction prediction : predictions)
{
if (prediction.getRouteName().equals(currentRouteName) == false)
{
newPredictions.add(prediction);
}
}
predictions.clear();
predictions.addAll(newPredictions);
}
else
{
predictions.clear();
}
}
}
public void addPredictionIfNotExists(IPrediction prediction)
{
synchronized (modificationLock) {
if (predictions.contains(prediction) == false)
{
predictions.add(prediction);
}
}
}
public PredictionView getPredictionView() {
synchronized (modificationLock) {
// in case predictionView is still being constructed
return predictionView;
}
}
}