MATSIM
MatsimEventsReader.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * MatsimEventsReader.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 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.core.events;
22 
23 import java.io.InputStream;
24 import java.net.URL;
25 import java.util.LinkedHashMap;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Stack;
29 
30 import org.apache.logging.log4j.LogManager;
31 import org.apache.logging.log4j.Logger;
38 import org.xml.sax.Attributes;
39 import org.xml.sax.SAXException;
40 
47 public final class MatsimEventsReader implements MatsimReader {
48 
49  private final static Logger log = LogManager.getLogger(MatsimEventsReader.class);
50  private final EventsManager events;
51 
52  private final Map<String, CustomEventMapper> customEventMappers = new LinkedHashMap<>();
53 
54  public interface CustomEventMapper {
55  Event apply(GenericEvent event);
56  }
57 
58  public void addCustomEventMapper(String eventType, CustomEventMapper mapper) {
59  this.customEventMappers.put(eventType, mapper);
60  }
61 
67  public MatsimEventsReader(final EventsManager events) {
68  this.events = events;
69  }
70 
76  @Override
77  public void readFile(final String filename) {
78  String lcFilename = filename.toLowerCase(Locale.ROOT);
79  if (lcFilename.endsWith(".xml") || lcFilename.endsWith(".xml.gz") || lcFilename.endsWith(".xml.zst") || lcFilename.endsWith(".xml.lz4")) {
80  new XmlEventsReader(this.events, this.customEventMappers).readFile(filename );
81  } else if (lcFilename.endsWith(".ndjson") || lcFilename.endsWith(".ndjson.gz") || lcFilename.endsWith(".ndjson.zst")) {
82  EventsReaderJson reader = new EventsReaderJson(this.events);
83  customEventMappers.forEach(reader::addCustomEventMapper);
84  reader.parse(filename);
85  } else if (lcFilename.endsWith(".txt") || lcFilename.endsWith(".txt.gz")) {
86  throw new RuntimeException("text events are no longer supported. Please use MATSim 0.6.1 or earlier to read text events.");
87  } else {
88  throw new IllegalArgumentException("Cannot recognize the format of the events-file " + filename);
89  }
90  }
91 
92  @Deprecated // use readStream(InputStream, EventsFileFormat)
93  public void readStream(final InputStream stream) {
94  new XmlEventsReader(this.events, this.customEventMappers).parse(stream );
95  }
96 
97  public void readStream(final InputStream stream, final ControllerConfigGroup.EventsFileFormat format) {
98  switch (format) {
99  case xml:
100  new XmlEventsReader(this.events, this.customEventMappers).parse(stream);
101  break;
102  case pb:
103  throw new UnsupportedOperationException(
104  "PB (Protobuf) is currently not supported to read from a stream");
105  case json:
106  EventsReaderJson reader = new EventsReaderJson(this.events);
107  customEventMappers.forEach(reader::addCustomEventMapper);
108  reader.parse(stream);
109  break;
110  }
111  }
112 
113  @Override
114  public void readURL( final URL url ) {
115  if (url.getFile().contains(".xml")) {
116  new XmlEventsReader( this.events, this.customEventMappers).readURL( url );
117  } else if (url.getFile().contains(".ndjson")) {
118  EventsReaderJson reader = new EventsReaderJson(this.events);
119  customEventMappers.forEach(reader::addCustomEventMapper);
120  reader.parse(url);
121  }
122  }
123 
124  private static class XmlEventsReader extends MatsimXmlParser {
125 
126  final EventsManager events;
127  private final static String EVENTS_V1 = "events_v1.dtd";
128  private MatsimXmlEventsParser delegate = null;
129 
130  private final Map<String, CustomEventMapper> map ;
131 
132  private XmlEventsReader( final EventsManager events, Map<String, CustomEventMapper> map ) {
134  this.events = events;
135  this.map = map;
136  this.setValidating(false); // events-files have no DTD, thus they cannot validate
137  setDoctype("events_v1.dtd"); // manually set a doctype, otherwise delegate would not be initialized
138  }
139 
140  @Override
141  public void startTag(final String name, final Attributes atts, final Stack<String> context) {
142  this.delegate.startTag(name, atts, context);
143  }
144 
145  @Override
146  public void characters(char[] ch, int start, int length) throws SAXException {
147 // this.delegate.characters(ch, start, length);
148  // ignore characters to prevent OutOfMemoryExceptions
149  /* the events-file only contains empty tags with attributes,
150  * but without the dtd or schema, all whitespace between tags is handled
151  * by characters and added up by super.characters, consuming huge
152  * amount of memory when large events-files are read in.
153  */
154  }
155 
156  @Override
157  public void endTag(final String name, final String content, final Stack<String> context) {
158  this.delegate.endTag(name, content, context);
159  }
160 
161  @Override
162  protected void setDoctype(final String doctype) {
163  super.setDoctype(doctype);
164  // Currently the only events-type is v1
165  if (EVENTS_V1.equals(doctype)) {
166  this.delegate = new EventsReaderXMLv1(this.events);
167  map.forEach(delegate::addCustomEventMapper);
168  log.info("using events_v1-reader.");
169  } else {
170  throw new IllegalArgumentException("Doctype \"" + doctype + "\" not known.");
171  }
172  }
173  }
174 }
void endTag(final String name, final String content, final Stack< String > context)
void startTag(final String name, final Attributes atts, final Stack< String > context)
MatsimEventsReader(final EventsManager events)
void readStream(final InputStream stream, final ControllerConfigGroup.EventsFileFormat format)
final Map< String, CustomEventMapper > customEventMappers
final void readFile(final String filename)
void addCustomEventMapper(String eventType, CustomEventMapper mapper)
void readStream(final InputStream stream)
XmlEventsReader(final EventsManager events, Map< String, CustomEventMapper > map)