MATSIM
EventsReaderJson.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2020 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.core.events;
21 
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.UncheckedIOException;
27 import java.net.URL;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.zip.GZIPInputStream;
32 
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.Logger;
35 import org.matsim.api.core.v01.Coord;
36 import org.matsim.api.core.v01.Id;
66 import org.matsim.core.utils.io.IOUtils;
72 import org.matsim.vehicles.Vehicle;
73 
74 import com.fasterxml.jackson.core.JsonProcessingException;
75 import com.fasterxml.jackson.databind.JsonNode;
76 import com.fasterxml.jackson.databind.ObjectMapper;
77 import com.github.luben.zstd.ZstdInputStream;
78 
82 public final class EventsReaderJson {
83 
84  private final static Logger LOG = LogManager.getLogger(EventsReaderJson.class);
85  private final static ObjectMapper MAPPER = new ObjectMapper();
86 
87  private final EventsManager events;
88  private final Map<String, CustomEventMapper> customEventMappers = new HashMap<>();
89 
90  public EventsReaderJson(final EventsManager events) {
91  this.events = events;
92  }
93 
94  public void addCustomEventMapper(String eventType, CustomEventMapper cem) {
95  this.customEventMappers.put(eventType, cem);
96  }
97 
98  void parse(final String filename) throws UncheckedIOException {
99  parse(IOUtils.getBufferedReader(filename), filename);
100  }
101 
102  void parse(final InputStream stream) throws UncheckedIOException {
103  parse(new BufferedReader(new InputStreamReader(stream)), "stream");
104  }
105 
106  void parse(URL url) throws UncheckedIOException {
107  LOG.info("starting to parse json from url " + url + " ...");
108  try (InputStream urlStream = url.openStream()) {
109  InputStream inStream = urlStream;
110  if (url.getFile().endsWith(".gz")) {
111  inStream = new GZIPInputStream(urlStream);
112  }
113  if (url.getFile().endsWith(".zst")) {
114  inStream = new ZstdInputStream(urlStream);
115  }
116  parse(inStream);
117  } catch (IOException e) {
118  throw new UncheckedIOException(e);
119  }
120  }
121 
122  private void parse(final BufferedReader in, final String filename) throws UncheckedIOException {
123  try {
124  String line;
125  while ((line = in.readLine()) != null) {
126  parseLine(line);
127  }
128  try {
129  in.close();
130  }
131  catch (IOException e) {
132  LOG.error("Could not close file: " + filename, e);
133  }
134  } catch (IOException e) {
135  throw new UncheckedIOException(e);
136  }
137  }
138 
139  private void parseLine(final String line) throws JsonProcessingException, IOException {
140  JsonNode o = MAPPER.reader().readTree(line);
141  parseEvent(o);
142  }
143 
144  private void parseEvent(JsonNode o) {
145  String eventType = o.get("type").asText();
146  double time = o.get("time").asDouble();
147 
148  // === material related to wait2link below here ===
149  if (LinkLeaveEvent.EVENT_TYPE.equals(eventType)) {
150  this.events.processEvent(new LinkLeaveEvent(time,
151  Id.create(o.get(LinkLeaveEvent.ATTRIBUTE_VEHICLE).asText(), Vehicle.class),
152  Id.create(o.get(LinkLeaveEvent.ATTRIBUTE_LINK).asText(), Link.class)
153  // had driver id in previous version
154  ));
155  } else if (LinkEnterEvent.EVENT_TYPE.equals(eventType)) {
156  this.events.processEvent(new LinkEnterEvent(time,
157  Id.create(o.get(LinkEnterEvent.ATTRIBUTE_VEHICLE).asText(), Vehicle.class),
158  Id.create(o.get(LinkEnterEvent.ATTRIBUTE_LINK).asText(), Link.class)
159  // had driver id in previous version
160  ));
161  } else if (VehicleEntersTrafficEvent.EVENT_TYPE.equals(eventType)) {
162  // (this is the new version, marked by the new events name)
163 
164  this.events.processEvent(new VehicleEntersTrafficEvent(time,
165  Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Person.class),
166  Id.create(o.get(VehicleEntersTrafficEvent.ATTRIBUTE_LINK).asText(), Link.class),
170  ));
171  } else if ("wait2link".equals(eventType)) {
172  // (this is the old version, marked by the old events name)
173 
174  // retrofit vehicle Id:
175  Id<Vehicle> vehicleId;
177  vehicleId = Id.create(o.get(VehicleEntersTrafficEvent.ATTRIBUTE_VEHICLE).asText(), Vehicle.class);
178  } else {
179  // for the old events type, we set the vehicle id to the driver id if the vehicle id does not exist:
180  vehicleId = Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Vehicle.class);
181  }
182  // retrofit position:
183  double position = o.path(VehicleEntersTrafficEvent.ATTRIBUTE_POSITION).asDouble(1.0);
184  this.events.processEvent(new VehicleEntersTrafficEvent(time,
185  Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Person.class),
186  Id.create(o.get(VehicleEntersTrafficEvent.ATTRIBUTE_LINK).asText(), Link.class),
187  vehicleId,
189  position
190  ));
191  } else if (VehicleLeavesTrafficEvent.EVENT_TYPE.equals(eventType)) {
192  this.events.processEvent(new VehicleLeavesTrafficEvent(time,
194  Id.create(o.get(VehicleLeavesTrafficEvent.ATTRIBUTE_LINK).asText(), Link.class),
198  ));
199  }
200  // === material related to wait2link above here
201  else if (ActivityEndEvent.EVENT_TYPE.equals(eventType)) {
202  Coord coord = null;
203  if (o.has(Event.ATTRIBUTE_X)) {
204  double xx = o.get(Event.ATTRIBUTE_X).asDouble();
205  double yy = o.get(Event.ATTRIBUTE_Y).asDouble();
206  coord = new Coord(xx, yy);
207  }
208  this.events.processEvent(new ActivityEndEvent(
209  time,
210  Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Person.class),
211  Id.create(o.get(HasLinkId.ATTRIBUTE_LINK).asText(), Link.class),
213  o.get(ActivityEndEvent.ATTRIBUTE_ACTTYPE).asText(),
214  coord));
215  } else if (ActivityStartEvent.EVENT_TYPE.equals(eventType)) {
216  Coord coord = null;
217  if (o.has(Event.ATTRIBUTE_X)) {
218  double xx = o.get(Event.ATTRIBUTE_X).asDouble();
219  double yy = o.get(Event.ATTRIBUTE_Y).asDouble();
220  coord = new Coord(xx, yy);
221  }
222  try {
223  this.events.processEvent(new ActivityStartEvent(
224  time,
225  Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Person.class),
226  Id.create(o.get(HasLinkId.ATTRIBUTE_LINK).asText(), Link.class),
228  o.get(ActivityStartEvent.ATTRIBUTE_ACTTYPE).asText(),
229  coord));
230  } catch (NullPointerException e) {
231  e.printStackTrace();
232  boolean hasFacility = o.has(HasFacilityId.ATTRIBUTE_FACILITY);
233  this.events.processEvent(new ActivityStartEvent(
234  time,
235  Id.create(o.get(HasPersonId.ATTRIBUTE_PERSON).asText(), Person.class),
236  Id.create(o.get(HasLinkId.ATTRIBUTE_LINK).asText(), Link.class),
237  hasFacility ? Id.create(o.get(HasFacilityId.ATTRIBUTE_FACILITY).asText(), ActivityFacility.class) : null,
238  o.get(ActivityStartEvent.ATTRIBUTE_ACTTYPE).asText(),
239  coord));
240  }
241  } else if (PersonArrivalEvent.EVENT_TYPE.equals(eventType)) {
242  String legMode = o.path(PersonArrivalEvent.ATTRIBUTE_LEGMODE).asText(null);
243  String mode = legMode == null ? null : legMode.intern();
244  this.events.processEvent(new PersonArrivalEvent(
245  time,
246  Id.create(o.get(PersonArrivalEvent.ATTRIBUTE_PERSON).asText(), Person.class),
247  Id.create(o.get(PersonArrivalEvent.ATTRIBUTE_LINK).asText(), Link.class),
248  mode));
249  } else if (PersonDepartureEvent.EVENT_TYPE.equals(eventType)) {
250  String legMode = o.path(PersonDepartureEvent.ATTRIBUTE_LEGMODE).asText(null);
251  String canonicalLegMode = legMode == null ? null : legMode.intern();
252  String routingMode = o.path(PersonDepartureEvent.ATTRIBUTE_ROUTING_MODE).asText(null);
253  String canonicalRoutingMode = routingMode == null ? null : routingMode.intern();
254  this.events.processEvent(new PersonDepartureEvent(
255  time,
256  Id.create(o.get(PersonDepartureEvent.ATTRIBUTE_PERSON).asText(), Person.class),
257  Id.create(o.get(PersonDepartureEvent.ATTRIBUTE_LINK).asText(), Link.class),
258  canonicalLegMode, canonicalRoutingMode));
259  } else if (PersonStuckEvent.EVENT_TYPE.equals(eventType)) {
260  String legMode = o.path(PersonStuckEvent.ATTRIBUTE_LEGMODE).asText(null);
261  String mode = legMode == null ? null : legMode.intern();
262  String linkIdString = o.path(PersonStuckEvent.ATTRIBUTE_LINK).asText(null);
263  Id<Link> linkId = linkIdString == null ? null : Id.create(linkIdString, Link.class); // linkId is optional
264  this.events.processEvent(new PersonStuckEvent(
265  time,
266  Id.create(o.get(PersonStuckEvent.ATTRIBUTE_PERSON).asText(), Person.class),
267  linkId,
268  mode));
269  } else if (VehicleAbortsEvent.EVENT_TYPE.equals(eventType)) {
270  String linkIdString = o.path(VehicleAbortsEvent.ATTRIBUTE_LINK).asText(null);
271  Id<Link> linkId = linkIdString == null ? null : Id.create(linkIdString, Link.class);
272  this.events.processEvent(new VehicleAbortsEvent(
273  time,
274  Id.create(o.get(VehicleAbortsEvent.ATTRIBUTE_VEHICLE).asText(), Vehicle.class),
275  linkId));
276  } else if (PersonMoneyEvent.EVENT_TYPE.equals(eventType) || "agentMoney".equals(eventType)) {
277  this.events.processEvent(new PersonMoneyEvent(
278  time,
279  Id.create(o.get(PersonMoneyEvent.ATTRIBUTE_PERSON).asText(), Person.class),
280  o.get(PersonMoneyEvent.ATTRIBUTE_AMOUNT).asDouble(),
281  o.path(PersonMoneyEvent.ATTRIBUTE_PURPOSE).asText(null),
282  o.path(PersonMoneyEvent.ATTRIBUTE_TRANSACTION_PARTNER).asText(null)));
283  } else if (PersonScoreEvent.EVENT_TYPE.equals(eventType) || "personScore".equals(eventType)) {
284  this.events.processEvent(new PersonScoreEvent(
285  time,
286  Id.create(o.get(PersonScoreEvent.ATTRIBUTE_PERSON).asText(), Person.class),
287  o.get(PersonScoreEvent.ATTRIBUTE_AMOUNT).asDouble(),
288  o.path(PersonScoreEvent.ATTRIBUTE_KIND).asText(null)));
289  } else if (PersonEntersVehicleEvent.EVENT_TYPE.equals(eventType)) {
290  this.events.processEvent(new PersonEntersVehicleEvent(
291  time,
292  Id.create(o.get(PersonEntersVehicleEvent.ATTRIBUTE_PERSON).asText(), Person.class),
293  Id.create(o.get(PersonEntersVehicleEvent.ATTRIBUTE_VEHICLE).asText(), Vehicle.class)));
294  } else if (PersonLeavesVehicleEvent.EVENT_TYPE.equals(eventType)) {
295  Id<Person> pId = Id.create(o.get(PersonLeavesVehicleEvent.ATTRIBUTE_PERSON).asText(), Person.class);
297  this.events.processEvent(new PersonLeavesVehicleEvent(time, pId, vId));
298  } else if (TeleportationArrivalEvent.EVENT_TYPE.equals(eventType)) {
299  this.events.processEvent(new TeleportationArrivalEvent(
300  time,
303  o.path(TeleportationArrivalEvent.ATTRIBUTE_MODE).asText(null)));
304  } else if (VehicleArrivesAtFacilityEvent.EVENT_TYPE.equals(eventType)) {
305  double delay = o.path(VehicleArrivesAtFacilityEvent.ATTRIBUTE_DELAY).asDouble(0.0);
307  time,
310  delay));
311  } else if (VehicleDepartsAtFacilityEvent.EVENT_TYPE.equals(eventType)) {
312  double delay = o.get(VehicleDepartsAtFacilityEvent.ATTRIBUTE_DELAY).asDouble(0.0);
314  time,
317  delay));
318  } else if (TransitDriverStartsEvent.EVENT_TYPE.equals(eventType)) {
319  this.events.processEvent(new TransitDriverStartsEvent(
320  time,
326  } else if (BoardingDeniedEvent.EVENT_TYPE.equals(eventType)){
327  Id<Person> personId = Id.create(o.get(BoardingDeniedEvent.ATTRIBUTE_PERSON_ID).asText(), Person.class);
328  Id<Vehicle> vehicleId = Id.create(o.get(BoardingDeniedEvent.ATTRIBUTE_VEHICLE_ID).asText(), Vehicle.class);
329  this.events.processEvent(new BoardingDeniedEvent(time, personId, vehicleId));
330  } else if (AgentWaitingForPtEvent.EVENT_TYPE.equals(eventType)){
331  Id<Person> agentId = Id.create(o.get(AgentWaitingForPtEvent.ATTRIBUTE_AGENT).asText(), Person.class);
334  this.events.processEvent(new AgentWaitingForPtEvent(time, agentId, waitStopId, destinationStopId));
335  } else {
336  GenericEvent event = new GenericEvent(eventType, time);
337 
338  Iterator<Map.Entry<String, JsonNode>> iter = o.fields();
339  while (iter.hasNext()) {
340  Map.Entry<String, JsonNode> e = iter.next();
341  String key = e.getKey();
342  if (key.equals("time") || key.equals("type")) {
343  continue;
344  }
345  String value = e.getValue().asText(null);
346  event.getAttributes().put(key, value);
347  }
348  CustomEventMapper cem = this.customEventMappers.get(eventType);
349  if (cem != null) {
350  this.events.processEvent(cem.apply(event));
351  } else {
352  this.events.processEvent(event);
353  }
354  }
355  }
356 
357 }
static< T > Id< T > get(int index, final Class< T > type)
Definition: Id.java:112
static BufferedReader getBufferedReader(URL url, Charset charset)
Definition: IOUtils.java:321
EventsReaderJson(final EventsManager events)
static final String ATTRIBUTE_X
Definition: Event.java:35
static< T > Id< T > create(final long key, final Class< T > type)
Definition: Id.java:68
final Map< String, CustomEventMapper > customEventMappers
void parse(final BufferedReader in, final String filename)
static final String ATTRIBUTE_Y
Definition: Event.java:36
void addCustomEventMapper(String eventType, CustomEventMapper cem)