@Override
    public CoachShuttleGatheringSolution readSolution() throws IOException {
      solution = new CoachShuttleGatheringSolution();
      solution.setId(0L);
      readLocationList();
      busOrStopOrHubId = 0L;
      readBusList();
      readBusStopList();

      int busListSize = solution.getCoachList().size() + solution.getShuttleList().size();
      int base = solution.getStopList().size() + solution.getShuttleList().size();
      BigInteger possibleSolutionSize =
          factorial(base + busListSize - 1).divide(factorial(busListSize - 1));
      logger.info(
          "CoachShuttleGathering {} has {} road locations, {} coaches, {} shuttles and {} bus stops"
              + " with a search space of {}.",
          getInputId(),
          solution.getLocationList().size(),
          solution.getCoachList().size(),
          solution.getShuttleList().size(),
          solution.getStopList().size(),
          getFlooredPossibleSolutionSize(possibleSolutionSize));
      return solution;
    }
 private void readBusStopList() throws IOException {
   List<BusStop> busStopList = new ArrayList<>();
   bufferedReader.readLine(); // Ignore first line (comment)
   for (String line = bufferedReader.readLine();
       line != null;
       line = bufferedReader.readLine()) {
     if (line.isEmpty()) {
       continue;
     }
     String[] lineTokens = splitBySemicolonSeparatedValue(line, 8);
     String busStopType = lineTokens[0];
     String name = lineTokens[1];
     if (busStopType.equalsIgnoreCase("HUB")) {
       if (solution.getHub() != null) {
         throw new IllegalArgumentException(
             "The hub with name ("
                 + name
                 + ") is not the only hub ("
                 + solution.getHub().getName()
                 + ").");
       }
       BusHub hub = new BusHub();
       hub.setId(busOrStopOrHubId);
       busOrStopOrHubId++;
       hub.setName(name);
       // Ignore lineTokens[2] and lineTokens[3]
       double latitude = Double.parseDouble(lineTokens[4]);
       double longitude = Double.parseDouble(lineTokens[5]);
       RoadLocation location = latLongToLocationMap.get(Arrays.asList(latitude, longitude));
       if (location == null) {
         throw new IllegalArgumentException(
             "The bus stop with name ("
                 + name
                 + ") has a coordinate ("
                 + latitude
                 + ", "
                 + longitude
                 + ") which is not in the coordinates file.");
       }
       hub.setLocation(location);
       int passengerQuantity = Integer.parseInt(lineTokens[6]);
       if (passengerQuantity != 0) {
         throw new IllegalArgumentException(
             "The hub with name ("
                 + name
                 + ") has an unsupported passengerQuantity ("
                 + passengerQuantity
                 + ").");
       }
       int transportTimeLimit = Integer.parseInt(lineTokens[7]);
       if (transportTimeLimit != 0) {
         throw new IllegalArgumentException(
             "The hub with name ("
                 + name
                 + ") has an unsupported transportTimeLimit ("
                 + transportTimeLimit
                 + ").");
       }
       for (Coach coach : solution.getCoachList()) {
         coach.setDestination(hub);
       }
       ArrayList<Shuttle> transferShuttleList =
           new ArrayList<>(solution.getShuttleList().size());
       for (Shuttle shuttle : solution.getShuttleList()) {
         // TODO Use a fixed value Construction Heuristic to initialize the destination variable
         shuttle.setDestination(hub);
         transferShuttleList.add(shuttle);
       }
       hub.setTransferShuttleList(transferShuttleList);
       solution.setHub(hub);
     } else if (busStopType.equalsIgnoreCase("BUSSTOP")) {
       BusStop busStop = new BusStop();
       busStop.setId(busOrStopOrHubId);
       busOrStopOrHubId++;
       busStop.setName(name);
       // Ignore lineTokens[2] and lineTokens[3]
       double latitude = Double.parseDouble(lineTokens[4]);
       double longitude = Double.parseDouble(lineTokens[5]);
       RoadLocation location = latLongToLocationMap.get(Arrays.asList(latitude, longitude));
       if (location == null) {
         throw new IllegalArgumentException(
             "The bus stop with name ("
                 + name
                 + ") has a coordinate ("
                 + latitude
                 + ", "
                 + longitude
                 + ") which is not in the coordinates file.");
       }
       busStop.setLocation(location);
       busStop.setPassengerQuantity(Integer.parseInt(lineTokens[6]));
       busStop.setTransportTimeLimit(Integer.parseInt(lineTokens[7]));
       // Trade memory for performance (might not be desired if it is too memory hungry)
       busStop.setTransferShuttleList(new ArrayList<>(solution.getShuttleList().size()));
       busStopList.add(busStop);
     } else {
       throw new IllegalArgumentException(
           "The bus stop with name ("
               + name
               + ") has an unsupported type ("
               + busStopType
               + ").");
     }
   }
   solution.setStopList(busStopList);
 }