/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.fares; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.onebusaway.gtfs.services.GtfsRelationalDao; import org.opentripplanner.routing.bike_rental.TimeBasedBikeRentalFareServiceFactory; import org.opentripplanner.routing.impl.DefaultFareServiceFactory; import org.opentripplanner.routing.services.FareService; import org.opentripplanner.routing.services.FareServiceFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; public abstract class MultipleFareServiceFactory implements FareServiceFactory { private static Logger log = LoggerFactory .getLogger(MultipleFareServiceFactory.class); private List<FareServiceFactory> subFactories; @Override public FareService makeFareService() { List<FareService> subServices = new ArrayList<>(); for (FareServiceFactory subFactory : subFactories) subServices.add(subFactory.makeFareService()); return makeMultipleFareService(subServices); } protected abstract FareService makeMultipleFareService(List<FareService> subServices); @Override public void processGtfs(GtfsRelationalDao dao) { for (FareServiceFactory subFactory : subFactories) subFactory.processGtfs(dao); } /** * Accept several ways to define fares to compose. Examples: * * <pre> * { combinationStrategy : "additive", * // An array of 'fares' * fares : [ "seattle", { ... } ] * } * -------------------------- * { combinationStrategy : "additive", * // All properties starting with 'fare' * fare1 : "seattle", * fare2 : { type: "bike-rental-time-based", * prices : { ... } * } } * </pre> */ @Override public void configure(JsonNode config) { subFactories = new ArrayList<>(); for (JsonNode pConfig : config.path("fares")) { subFactories.add(DefaultFareServiceFactory.fromConfig(pConfig)); } for (Iterator<Map.Entry<String, JsonNode>> i = config.fields(); i.hasNext();) { Map.Entry<String, JsonNode> kv = i.next(); String key = kv.getKey(); if (key.startsWith("fare") && !key.equals("fares")) { JsonNode node = kv.getValue(); FareServiceFactory fareFactory = DefaultFareServiceFactory.fromConfig(node); if (fareFactory != null) subFactories.add(fareFactory); } } if (subFactories.isEmpty()) throw new IllegalArgumentException( "Empty fare composite. Please specify either a 'fares' array or a list of 'fareXxx' properties"); if (subFactories.size() == 1) { // Legal, but suspicious. log.warn("Fare composite has only ONE fare to combine. This is allowed, but useless. Did you forgot to define a second fare to combine?"); } } public static class AddingMultipleFareServiceFactory extends MultipleFareServiceFactory { @Override protected FareService makeMultipleFareService(List<FareService> subServices) { return new AddingMultipleFareService(subServices); } } }