MATSIM
NetworkReaderMatsimV2.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * NetworkReaderMatsimV1.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.network.io;
22 
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.matsim.api.core.v01.Coord;
26 import org.matsim.api.core.v01.Id;
37 import org.matsim.core.utils.misc.Time;
40 import org.xml.sax.Attributes;
41 
42 import java.util.HashSet;
43 import java.util.Map;
44 import java.util.Set;
45 import java.util.Stack;
46 
49 
55 final class NetworkReaderMatsimV2 extends MatsimXmlParser {
56 
57  private final static String NETWORK = "network";
58  private final static String LINKS = "links";
59  private final static String NODE = "node";
60  private final static String LINK = "link";
61  private final Network network;
62 
63  private final AttributesXmlReaderDelegate attributesDelegate = new AttributesXmlReaderDelegate();
64  private org.matsim.utils.objectattributes.attributable.Attributes currentAttributes = null;
65 
66  private final String externalInputCRS;
67  private final String targetCRS;
68  private CoordinateTransformation coordinateTransformation = new IdentityTransformation();
69 
70  private final static Logger log = LogManager.getLogger(NetworkReaderMatsimV2.class);
71 
72  NetworkReaderMatsimV2(
73  final String inputCRS,
74  final String targetCRS,
75  final Network network) {
76  super(ValidationType.DTD_ONLY);
77  this.externalInputCRS = inputCRS;
78  this.targetCRS = targetCRS;
79  if (externalInputCRS != null && targetCRS != null) {
80  this.coordinateTransformation = TransformationFactory.getCoordinateTransformation(externalInputCRS, targetCRS);
81  ProjectionUtils.putCRS(network, targetCRS);
82  }
83  this.network = network;
84  }
85 
86  @Override
87  public void startTag(final String name, final Attributes atts, final Stack<String> context) {
88  switch( name ){
89  case NODE -> startNode( atts );
90  case LINK -> startLink( atts );
91  case NETWORK -> startNetwork( atts );
92  case LINKS -> startLinks( atts );
93  case TAG_ATTRIBUTES, TAG_ATTRIBUTE -> attributesDelegate.startTag( name, atts, context, currentAttributes );
94 // default -> throw new IllegalStateException( "Unexpected value: " + name );
95  // (there is at least "nodes" which just passes through. I found it that way. kai, dec'24)
96  }
97  }
98 
99  @Override
100  public void endTag(final String name, final String content, final Stack<String> context) {
101  switch( name ) {
102  case TAG_ATTRIBUTES:
103  if (context.peek().equals(NETWORK)) {
104  String inputCRS = (String) network.getAttributes().getAttribute(ProjectionUtils.INPUT_CRS_ATT);
105  if (inputCRS != null && targetCRS != null) {
106  if (externalInputCRS != null) {
107  // warn or crash?
108  log.warn("coordinate transformation defined both in config and in input file: setting from input file will be used");
109  }
110  coordinateTransformation = TransformationFactory.getCoordinateTransformation(inputCRS, targetCRS);
111  ProjectionUtils.putCRS(network, targetCRS);
112  }
113  }
114  /* fall-through */
115  case TAG_ATTRIBUTE:
116  attributesDelegate.endTag(name, content, context);
117  break;
118  }
119  }
120 
121  private void startNetwork(final Attributes atts) {
122  if (atts.getValue("type") != null) {
123  log.info("Attribute 'type' is deprecated. There's always only ONE network, where the links and nodes define, which " +
124  "transportation mode is allowed to use it (for the future)");
125  }
126  this.network.setName(atts.getValue("name"));
127  if (atts.getValue("capDivider") != null) {
128  log.warn("capDivider defined. it will be used but should be gone eventually. " +
129  "-- This is a weird comment, since the matsim public api tells to put this into the network rather than" +
130  " into the ``links''. kai, jun'11");
131  String capperiod = atts.getValue("capDivider") + ":00:00";
132  this.network.setCapacityPeriod(Time.parseTime(capperiod));
133  }
134 
135  currentAttributes = network.getAttributes();
136  }
137 
138  private void startLinks(final Attributes atts) {
139  double capacityPeriod = 3600.0; //the default of one hour
140  String capperiod = atts.getValue("capperiod");
141  if (capperiod != null) {
142  capacityPeriod = Time.parseTime(capperiod);
143  }
144  else {
145  log.warn("capperiod was not defined. Using default value of " + Time.writeTime(capacityPeriod) + ".");
146  }
147  this.network.setCapacityPeriod(capacityPeriod);
148 
149  String effectivecellsize = atts.getValue("effectivecellsize");
150  if (effectivecellsize == null){
151  this.network.setEffectiveCellSize(7.5); // we use a default cell size of 7.5 meters
152  } else {
153  this.network.setEffectiveCellSize(Double.parseDouble(effectivecellsize));
154  }
155 
156  String effectivelanewidth = atts.getValue("effectivelanewidth");
157  if (effectivelanewidth == null) {
158  this.network.setEffectiveLaneWidth(3.75); // the default lane width is 3.75
159  } else {
160  this.network.setEffectiveLaneWidth(Double.parseDouble(effectivelanewidth));
161  }
162 
163  if ((atts.getValue("capPeriod") != null) || (atts.getValue("capDivider") != null) || (atts.getValue("capdivider") != null)) {
164  log.warn("Found capPeriod, capDivider and/or capdivider in the links element. They will be ignored, since they " +
165  "should be set in the network element. -- This is a weird warning, since setting them in the " +
166  "network element also produces a warning.");
167  log.warn("At this point, it seems that, in network.xml, one sets capperiod in the `links' section, but in the " +
168  "matsim api, the corresponding entry belongs into the `network' object. kai, jun'11") ;
169  }
170  }
171 
172  private void startNode(final Attributes atts) {
173  final Node node =
174  this.network.getFactory().createNode(
175  Id.create(atts.getValue("id"), Node.class),
176  parseCoord(atts));
177  this.network.addNode(node);
178 
179  NetworkUtils.setType(node,atts.getValue("type"));
180  // (did not have a null check when I found it. kai, jul'16)
181 
182  if (atts.getValue(NetworkUtils.ORIGID) != null) {
183  NetworkUtils.setOrigId( node, atts.getValue(NetworkUtils.ORIGID) ) ;
184  }
185 
186  currentAttributes = node.getAttributes();
187  }
188 
189  private Coord parseCoord(Attributes atts) {
190  final Coord c = atts.getValue( "z" ) == null ?
191  new Coord(
192  Double.parseDouble(atts.getValue("x")),
193  Double.parseDouble(atts.getValue("y"))) :
194  new Coord(
195  Double.parseDouble(atts.getValue("x")),
196  Double.parseDouble(atts.getValue("y")),
197  Double.parseDouble(atts.getValue("z")));
198  return coordinateTransformation.transform( c );
199  }
200 
201  private void startLink(final Attributes atts) {
202  final String fromNodeStr = atts.getValue("from");
203  Node fromNode = this.network.getNodes().get(Id.create(fromNodeStr, Node.class));
204  if ( fromNode==null ) {
205  throw new RuntimeException("node id given by link cannot be dereferenced; node label=" + fromNodeStr ) ;
206  }
207  final String toNodeStr = atts.getValue("to");
208  Node toNode = this.network.getNodes().get(Id.create(toNodeStr, Node.class));
209  if ( toNode==null ) {
210  throw new RuntimeException("node id given by link cannot be dereferenced; node label=" + toNodeStr ) ;
211  }
212  Link l = this.network.getFactory().createLink(Id.create(atts.getValue("id"), Link.class), fromNode, toNode);
213  l.setLength(Double.parseDouble(atts.getValue("length")));
214  l.setFreespeed(Double.parseDouble(atts.getValue("freespeed")));
215  l.setCapacity(Double.parseDouble(atts.getValue("capacity")));
216  l.setNumberOfLanes(Double.parseDouble(atts.getValue("permlanes")));
217  this.network.addLink(l);
218  {
219  String value = atts.getValue(NetworkUtils.ORIGID);
220  if ( value != null ) {
221  NetworkUtils.setOrigId( (l), value ) ; // will now put it into the attributes. kai, dec'16
222  }
223  }
224  {
225  final String value = atts.getValue(NetworkUtils.TYPE);
226  if ( value != null ) {
227  NetworkUtils.setType( (l), value); // will now put it into the attributes. kai, dec'16
228  }
229  }
230 
231  if (atts.getValue("modes") != null) {
232  String[] strModes = StringUtils.explode(atts.getValue("modes"), ',');
233  if ((strModes.length == 1) && strModes[0].isEmpty()) {
234  l.setAllowedModes(new HashSet<String>());
235  } else {
236  Set<String> modes = new HashSet<>();
237  for (String strMode : strModes) {
238  modes.add(strMode.trim().intern());
239  }
240  l.setAllowedModes(modes);
241  }
242  }
243 
244  currentAttributes = l.getAttributes();
245  }
246 
247  public void putAttributeConverters(Map<Class<?>, AttributeConverter<?>> converters) {
248  this.attributesDelegate.putAttributeConverters( converters );
249  }
250 }
static double parseDouble(String value)