MATSIM
TransitScheduleReaderV1.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * TransitScheduleReader.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2009 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.pt.transitSchedule;
22 
23 import java.util.ArrayList;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Stack;
28 import java.util.concurrent.ConcurrentHashMap;
29 
30 import org.matsim.api.core.v01.Coord;
31 import org.matsim.api.core.v01.Id;
32 import org.matsim.api.core.v01.Scenario;
39 import org.matsim.core.utils.misc.Time;
46 import org.matsim.vehicles.Vehicle;
47 import org.xml.sax.Attributes;
48 
55 
56  private final TransitSchedule schedule;
58 
62 
64  private final StringCache cache = new StringCache();
65 
66  public TransitScheduleReaderV1(final TransitSchedule schedule, final RouteFactories routeFactory) {
68  }
69 
70  public TransitScheduleReaderV1(final Scenario scenario) {
71  this( scenario.getTransitSchedule(),
73  }
74 
76  final CoordinateTransformation coordinateTransformation,
77  final Scenario scenario) {
79  scenario.getTransitSchedule(),
81  }
82 
84  CoordinateTransformation coordinateTransformation,
85  TransitSchedule schedule,
86  RouteFactories routeFactory) {
87  super(ValidationType.DTD_ONLY);
88  this.coordinateTransformation = coordinateTransformation;
89  this.schedule = schedule;
90  this.routeFactory = routeFactory;
91  }
92 
93  @Override
94  public void startTag(final String name, final Attributes atts, final Stack<String> context) {
95  if (Constants.STOP_FACILITY.equals(name)) {
96  boolean isBlocking = Boolean.parseBoolean(atts.getValue(Constants.IS_BLOCKING));
97  TransitStopFacility stop =
99  Id.create(
100  atts.getValue(Constants.ID),
101  TransitStopFacility.class),
102  coordinateTransformation.transform(
103  new Coord(
104  Double.parseDouble(atts.getValue("x")),
105  Double.parseDouble(atts.getValue("y")))),
106  isBlocking);
107  if (atts.getValue(Constants.LINK_REF_ID) != null) {
108  Id<Link> linkId = Id.create(atts.getValue(Constants.LINK_REF_ID), Link.class);
109  stop.setLinkId(linkId);
110  }
111  if (atts.getValue(Constants.NAME) != null) {
112  stop.setName(this.cache.get(atts.getValue(Constants.NAME)));
113  }
114  this.schedule.addStopFacility(stop);
115  } else if (Constants.TRANSIT_LINE.equals(name)) {
116  Id<TransitLine> id = Id.create(atts.getValue(Constants.ID), TransitLine.class);
117  this.currentTransitLine = schedule.getFactory().createTransitLine(id);
118  if (atts.getValue(Constants.NAME) != null) {
119  this.currentTransitLine.setName(atts.getValue(Constants.NAME));
120  }
121  this.schedule.addTransitLine(this.currentTransitLine);
122  } else if (Constants.TRANSIT_ROUTE.equals(name)) {
123  Id<TransitRoute> id = Id.create(atts.getValue(Constants.ID), TransitRoute.class);
124  this.currentTransitRoute = new TempTransitRoute(id);
125  } else if (Constants.DEPARTURE.equals(name)) {
126  Id<Departure> id = Id.create(atts.getValue(Constants.ID), Departure.class);
127  Departure departure = new DepartureImpl(id, Time.parseTime(atts.getValue("departureTime")));
128  String vehicleRefId = atts.getValue(Constants.VEHICLE_REF_ID);
129  if (vehicleRefId != null) {
130  departure.setVehicleId(Id.create(vehicleRefId, Vehicle.class));
131  }
132  this.currentTransitRoute.departures.put(id, departure);
133  } else if (Constants.ROUTE_PROFILE.equals(name)) {
134  this.currentRouteProfile = new TempRoute();
135  } else if (Constants.LINK.equals(name)) {
136  String linkStr = atts.getValue(Constants.REF_ID);
137  if (!linkStr.contains(" ")) {
138  this.currentRouteProfile.addLink(Id.create(linkStr, Link.class));
139  } else {
140  String[] links = linkStr.split(" ");
141  for (int i = 0; i < links.length; i++) {
142  this.currentRouteProfile.addLink(Id.create(links[i], Link.class));
143  }
144  }
145  } else if (Constants.STOP.equals(name)) {
146  Id<TransitStopFacility> id = Id.create(atts.getValue(Constants.REF_ID), TransitStopFacility.class);
147  TransitStopFacility facility = this.schedule.getFacilities().get(id);
148  if (facility == null) {
149  throw new RuntimeException("no stop/facility with id " + atts.getValue(Constants.REF_ID));
150  }
151  TransitRouteStopImpl.Builder stopBuilder = new TransitRouteStopImpl.Builder().stop(facility);
152  String arrival = atts.getValue(Constants.ARRIVAL_OFFSET);
153  String departure = atts.getValue(Constants.DEPARTURE_OFFSET);
154  if (arrival != null) {
155  Time.parseOptionalTime(arrival).ifDefined(stopBuilder::arrivalOffset);
156  }
157  if (departure != null) {
158  Time.parseOptionalTime(departure).ifDefined(stopBuilder::departureOffset);
159  }
160  stopBuilder.awaitDepartureTime(Boolean.parseBoolean(atts.getValue(Constants.AWAIT_DEPARTURE)));
161  this.currentTransitRoute.stopBuilders.add(stopBuilder);
162  }
163  }
164 
165  @Override
166  public void endTag(final String name, final String content, final Stack<String> context) {
167  if (Constants.DESCRIPTION.equals(name) && Constants.TRANSIT_ROUTE.equals(context.peek())) {
168  this.currentTransitRoute.description = content;
169  } else if (Constants.TRANSPORT_MODE.equals(name)) {
170  this.currentTransitRoute.mode = content.intern();
171  } else if (Constants.TRANSIT_ROUTE.equals(name)) {
172  List<TransitRouteStop> stops = new ArrayList<>(this.currentTransitRoute.stopBuilders.size());
173  this.currentTransitRoute.stopBuilders.forEach(stopBuilder -> stops.add(stopBuilder.build()));
174  NetworkRoute route = null;
175  if (this.currentRouteProfile.firstLinkId != null) {
176  if (this.currentRouteProfile.lastLinkId == null) {
177  this.currentRouteProfile.lastLinkId = this.currentRouteProfile.firstLinkId;
178  }
179  route = this.routeFactory.createRoute(NetworkRoute.class, this.currentRouteProfile.firstLinkId, this.currentRouteProfile.lastLinkId);
180  route.setLinkIds(this.currentRouteProfile.firstLinkId, this.currentRouteProfile.linkIds, this.currentRouteProfile.lastLinkId);
181  }
182  TransitRoute transitRoute = this.schedule.getFactory().createTransitRoute(this.currentTransitRoute.id, route, stops, this.currentTransitRoute.mode);
183  transitRoute.setDescription(this.currentTransitRoute.description);
184  for (Departure departure : this.currentTransitRoute.departures.values()) {
185  transitRoute.addDeparture(departure);
186  }
187  this.currentTransitLine.addRoute(transitRoute);
188  }
189  }
190 
191  private static class TempTransitRoute {
192  protected final Id<TransitRoute> id;
193  protected String description = null;
194  protected Map<Id<Departure>, Departure> departures = new LinkedHashMap<>();
195  /*package*/ List<TransitRouteStopImpl.Builder> stopBuilders = new ArrayList<>();
196  /*package*/ String mode = null;
197 
198  protected TempTransitRoute(final Id<TransitRoute> id) {
199  this.id = id;
200  }
201  }
202 
203  private static class TempRoute {
204  /*package*/ List<Id<Link>> linkIds = new ArrayList<Id<Link>>();
205  /*package*/ Id<Link> firstLinkId = null;
206  /*package*/ Id<Link> lastLinkId = null;
207 
208  protected TempRoute() {
209  // public constructor for private inner class
210  }
211 
212  protected void addLink(final Id<Link> linkId) {
213  if (this.firstLinkId == null) {
214  this.firstLinkId = linkId;
215  } else if (this.lastLinkId == null) {
216  this.lastLinkId = linkId;
217  } else {
218  this.linkIds.add(this.lastLinkId);
219  this.lastLinkId = linkId;
220  }
221  }
222 
223  }
224 
225  private static class StringCache {
226 
227  private ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<String, String>(10000);
228 
236  public String get(final String string) {
237  if (string == null) {
238  return null;
239  }
240  String s = cache.putIfAbsent(string, string);
241  if (s == null) {
242  return string;
243  }
244  return s;
245  }
246  }
247 
248 }
void ifDefined(DoubleConsumer action)
Map< Id< TransitStopFacility >, TransitStopFacility > getFacilities()
void addTransitLine(final TransitLine line)
TransitScheduleReaderV1(final TransitSchedule schedule, final RouteFactories routeFactory)
void addRoute(final TransitRoute transitRoute)
void setDescription(final String description)
void startTag(final String name, final Attributes atts, final Stack< String > context)
static< T > Id< T > create(final long key, final Class< T > type)
Definition: Id.java:68
static final OptionalTime parseOptionalTime(final String time)
Definition: Time.java:167
static final double parseTime(final String time)
Definition: Time.java:163
TransitScheduleReaderV1(CoordinateTransformation coordinateTransformation, TransitSchedule schedule, RouteFactories routeFactory)
void setVehicleId(final Id< Vehicle > vehicleId)
void addDeparture(final Departure departure)
abstract TransitLine createTransitLine(final Id< TransitLine > lineId)
abstract TransitStopFacility createTransitStopFacility(final Id< TransitStopFacility > facilityId, final Coord coordinate, final boolean blocksLane)
TransitScheduleReaderV1(final CoordinateTransformation coordinateTransformation, final Scenario scenario)
void addStopFacility(final TransitStopFacility stop)
TransitSchedule getTransitSchedule()
abstract TransitRoute createTransitRoute(final Id< TransitRoute > routeId, final NetworkRoute route, final List< TransitRouteStop > stops, final String mode)
void setLinkIds(final Id< Link > startLinkId, final List< Id< Link >> linkIds, final Id< Link > endLinkId)
void endTag(final String name, final String content, final Stack< String > context)