/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* 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.transit_data_federation.bundle.tasks.transit_graph;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.onebusaway.collections.FactoryMap;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.calendar.LocalizedServiceId;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.gtfs.services.calendar.CalendarService;
import org.onebusaway.transit_data_federation.services.transit_graph.ServiceIdActivation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ServiceIdOverlapCache {
private CalendarService _calendarService;
private Map<Set<LocalizedServiceId>, List<ServiceIdActivation>> _cache = new HashMap<Set<LocalizedServiceId>, List<ServiceIdActivation>>();
@Autowired
public void setCalendarService(CalendarService calendarService) {
_calendarService = calendarService;
}
public List<ServiceIdActivation> getOverlappingServiceIdCombinations(
Set<LocalizedServiceId> serviceIds) {
List<ServiceIdActivation> combinations = _cache.get(serviceIds);
if (combinations == null) {
combinations = computeCombinationsInternal(serviceIds);
_cache.put(new HashSet<LocalizedServiceId>(serviceIds), combinations);
}
return combinations;
}
private List<ServiceIdActivation> computeCombinationsInternal(
Set<LocalizedServiceId> serviceIds) {
Map<ServiceDate, Set<LocalizedServiceId>> serviceIdsByServiceDate = new FactoryMap<ServiceDate, Set<LocalizedServiceId>>(
new HashSet<LocalizedServiceId>());
for (LocalizedServiceId lsid : serviceIds) {
AgencyAndId serviceId = lsid.getId();
for (ServiceDate serviceDate : _calendarService.getServiceDatesForServiceId(serviceId))
serviceIdsByServiceDate.get(serviceDate).add(lsid);
}
Set<Set<LocalizedServiceId>> sets = new HashSet<Set<LocalizedServiceId>>();
sets.addAll(serviceIdsByServiceDate.values());
List<ServiceIdActivation> combinations = new ArrayList<ServiceIdActivation>();
for (Set<LocalizedServiceId> activeServiceIds : sets) {
Set<LocalizedServiceId> inactiveServiceIds = new HashSet<LocalizedServiceId>();
for (Set<LocalizedServiceId> combo2 : sets) {
if (isSubset(activeServiceIds, combo2))
inactiveServiceIds.addAll(combo2);
}
inactiveServiceIds.removeAll(activeServiceIds);
combinations.add(new ServiceIdActivation(list(activeServiceIds),
list(inactiveServiceIds)));
}
Collections.sort(combinations);
return combinations;
}
private <T> boolean isSubset(Set<T> potentialSubset, Set<T> potentialSuperset) {
if (potentialSubset.size() >= potentialSuperset.size())
return false;
for (T element : potentialSubset) {
if (!potentialSuperset.contains(element))
return false;
}
return true;
}
private List<LocalizedServiceId> list(
Collection<LocalizedServiceId> combination) {
List<LocalizedServiceId> serviceIds = new ArrayList<LocalizedServiceId>(
combination);
Collections.sort(serviceIds);
return serviceIds;
}
}