package fi.hsl.parkandride.core.service.reporting;
import fi.hsl.parkandride.core.domain.*;
import org.geolatte.geom.Geometry;
import java.util.*;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonMap;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;
final class ReportContext {
final Map<Long, Facility> facilities;
final Map<Long, Hub> hubs;
final Map<Long, Operator> operators;
final Map<Long, List<Facility>> facilitiesByHubId;
final Map<Long, List<Long>> facilityIdsByOperatorId;
final Map<Long, Set<Operator>> operatorsByHubId;
final Map<Long, List<Hub>> hubsByFacilityId;
final Map<Long, Region> regionByFacilityId;
final Map<Long, Region> regionByHubId;
final Long allowedOperatorId;
final Collection<Region> regions;
public ReportContext(ReportServiceSupport reportService, Long allowedOperatorId) {
this.allowedOperatorId = allowedOperatorId;
facilities = getFacilities(reportService, allowedOperatorId);
hubs = getHubs(reportService);
operators = getOperators(reportService, allowedOperatorId);
facilitiesByHubId = new HashMap<>();
hubsByFacilityId = new HashMap<>();
regionByHubId = new HashMap<>();
regionByFacilityId = new HashMap<>();
regions = reportService.regionRepository.getRegions();
hubs.values().forEach(hub -> {
List<Facility> hubFacilities = hub.facilityIds.stream().map(id -> facilities.get(id)).filter(f -> f != null).collect(toList());
facilitiesByHubId.put(hub.id, hubFacilities);
hubsToFacilities(hub, hubFacilities, hubsByFacilityId);
regionByHubId.put(hub.id, getRegion(hub.location));
});
facilities.values().forEach(facility -> {
regionByFacilityId.put(facility.id, getRegion(facility.location));
});
facilityIdsByOperatorId = facilities.values().stream().collect(groupingBy(f -> f.operatorId, mapping(f -> f.id, toList())));
operatorsByHubId = hubs.values().stream().collect(toMap(
hub -> hub.id,
hub -> facilitiesByHubId.getOrDefault(hub.id, emptyList())
.stream()
.map(fac -> fac.operatorId)
.map(opId -> operators.get(opId))
.collect(toSet())
));
}
private Region getRegion(Geometry location) {
for (Region r : regions) {
if (r.area.intersects(location)) {
return r;
}
};
return Region.UNKNOWN_REGION;
}
private Map<Long, Hub> getHubs(ReportServiceSupport reportService) {
HubSearch search = new HubSearch();
search.setLimit(10000);
List<Hub> hubs = reportService.hubService.search(search).results;
return hubs.stream().collect(toMap((Hub h) -> h.id, identity(), (u, v) -> u, LinkedHashMap::new));
}
private Map<Long, Facility> getFacilities(ReportServiceSupport reportService, Long allowedOperatorId) {
PageableFacilitySearch search = new PageableFacilitySearch();
search.setLimit(10000);
search.setOperatorId(allowedOperatorId);
List<FacilityInfo> facilityInfos = reportService.facilityService.search(search).results;
return facilityInfos.stream().map((FacilityInfo f) -> reportService.facilityService.getFacility(f.id)).collect(toMap((Facility f) -> f.id, identity(), (u, v) -> u, LinkedHashMap::new));
}
private Map<Long, Operator> getOperators(ReportServiceSupport reportService, Long allowedOperatorId) {
if (allowedOperatorId != null) {
return singletonMap(allowedOperatorId, reportService.operatorService.getOperator(allowedOperatorId));
}
OperatorSearch search = new OperatorSearch();
search.setLimit(10000);
List<Operator> operators = reportService.operatorService.search(search).results;
return operators.stream().collect(toMap((Operator o) -> o.id, identity(), (u, v) -> u, LinkedHashMap::new));
}
private void hubsToFacilities(Hub hub, List<Facility> hubFacilities, Map<Long, List<Hub>> hubsByFacilityId) {
for (Facility facility : hubFacilities) {
List<Hub> hubList = hubsByFacilityId.get(facility.id);
if (hubList == null) {
hubList = new ArrayList<>();
hubsByFacilityId.put(facility.id, hubList);
}
hubList.add(hub);
}
}
}