SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIXMLConnectionsHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for edge connections stored in XML
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <iostream>
36 #include <xercesc/sax/HandlerBase.hpp>
37 #include <xercesc/sax/AttributeList.hpp>
38 #include <xercesc/sax/SAXParseException.hpp>
39 #include <xercesc/sax/SAXException.hpp>
41 #include <netbuild/NBEdge.h>
42 #include <netbuild/NBEdgeCont.h>
43 #include <netbuild/NBNode.h>
47 #include <utils/common/ToString.h>
53 
54 #ifdef CHECK_MEMORY_LEAKS
55 #include <foreign/nvwa/debug_new.h>
56 #endif // CHECK_MEMORY_LEAKS
57 
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
63  SUMOSAXHandler("xml-connection-description"),
64  myEdgeCont(ec),
65  myHaveWarnedAboutDeprecatedLanes(false),
66  myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ?
67  MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {}
68 
69 
71 
72 
73 void
75  const SUMOSAXAttributes& attrs) {
76  if (element == SUMO_TAG_DELETE) {
77  bool ok = true;
78  std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok);
79  std::string to = attrs.getStringReporting(SUMO_ATTR_TO, 0, ok);
80  if (!ok) {
81  return;
82  }
83  // these connections were removed when the edge was deleted
84  if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
85  return;
86  }
87  NBEdge* fromEdge = myEdgeCont.retrieve(from);
88  NBEdge* toEdge = myEdgeCont.retrieve(to);
89  if (fromEdge == 0) {
90  myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
91  return;
92  }
93  if (toEdge == 0) {
94  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
95  return;
96  }
97  if (!fromEdge->isConnectedTo(toEdge)) {
98  WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
99  return;
100  }
101  int fromLane = -1; // Assume all lanes are to be reset.
102  int toLane = -1;
103  if (attrs.hasAttribute(SUMO_ATTR_LANE)
105  || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
106  if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
107  return;
108  }
109  // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
110  // In this case it's ok to encounter invalid lance indices
111  if (!fromEdge->hasConnectionTo(toEdge, toLane)) {
112  WRITE_WARNING("Edge '" + fromEdge->getID() + "' has no connection to lane " + toString(toLane) + " of edge '" + toEdge->getID() + "'; the connection cannot be reset.");
113  }
114  }
115  fromEdge->removeFromConnections(toEdge, fromLane, toLane);
116  }
117 
118  if (element == SUMO_TAG_CONNECTION) {
119  bool ok = true;
120  std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, "connection", ok);
121  std::string to = attrs.getOptStringReporting(SUMO_ATTR_TO, "connection", ok, "");
122  if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
123  return;
124  }
125  // extract edges
126  NBEdge* fromEdge = myEdgeCont.retrieve(from);
127  NBEdge* toEdge = to.length() != 0 ? myEdgeCont.retrieve(to) : 0;
128  // check whether they are valid
129  if (fromEdge == 0) {
130  myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
131  return;
132  }
133  if (toEdge == 0 && to.length() != 0) {
134  myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
135  return;
136  }
137  // parse optional lane information
139  parseLaneBound(attrs, fromEdge, toEdge);
140  } else {
141  fromEdge->addEdge2EdgeConnection(toEdge);
142  }
143  }
144  if (element == SUMO_TAG_PROHIBITION) {
145  bool ok = true;
146  std::string prohibitor = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITOR, 0, ok, "");
147  std::string prohibited = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITED, 0, ok, "");
148  if (!ok) {
149  return;
150  }
151  NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
152  NBConnection prohibitedC = parseConnection("prohibited", prohibited);
153  if (prohibitorC.getFrom() == 0 || prohibitedC.getFrom() == 0) {
154  // something failed
155  return;
156  }
157  NBNode* n = prohibitorC.getFrom()->getToNode();
158  n->addSortedLinkFoes(prohibitorC, prohibitedC);
159  }
160 }
161 
162 
164 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) {
165  // split from/to
166  size_t div = def.find("->");
167  if (div == std::string::npos) {
168  myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
169  return NBConnection(0, 0);
170  }
171  std::string fromDef = def.substr(0, div);
172  std::string toDef = def.substr(div + 2);
173 
174  // retrieve the edges
175  // check whether the definition includes a lane information (do not process it)
176  if (fromDef.find('_') != std::string::npos) {
177  fromDef = fromDef.substr(0, fromDef.find('_'));
178  }
179  if (toDef.find('_') != std::string::npos) {
180  toDef = toDef.substr(0, toDef.find('_'));
181  }
182  // retrieve them now
183  NBEdge* fromE = myEdgeCont.retrieve(fromDef);
184  NBEdge* toE = myEdgeCont.retrieve(toDef);
185  // check
186  if (fromE == 0) {
187  myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
188  return NBConnection(0, 0);
189  }
190  if (toE == 0) {
191  myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
192  return NBConnection(0, 0);
193  }
194  return NBConnection(fromE, toE);
195 }
196 
197 
198 void
200  if (to == 0) {
201  // do nothing if it's a dead end
202  return;
203  }
204  bool ok = true;
205  const bool mayDefinitelyPass = attrs.getOptBoolReporting(SUMO_ATTR_PASS, 0, ok, false);
206  if (!ok) {
207  return;
208  }
209  // get the begin and the end lane
210  int fromLane;
211  int toLane;
212  try {
213  if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
214  return;
215  }
216  if (!validateLaneInfo(false /* canLanesBeNegative */, from, to, fromLane, toLane)) {
217  return;
218  }
219  if (from->hasConnectionTo(to, toLane)) {
220  WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
221  }
222  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass)) {
223  NBEdge* nFrom = from;
224  bool toNext = true;
225  do {
226  if (nFrom->getToNode()->getOutgoingEdges().size() != 1) {
227  toNext = false;
228  break;
229  }
230  NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
231  if (t->getID().substr(0, t->getID().find('/')) != nFrom->getID().substr(0, nFrom->getID().find('/'))) {
232  toNext = false;
233  break;
234  }
235  if (toNext) {
236  nFrom = t;
237  }
238  } while (toNext);
239  if (nFrom == 0 || !nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) {
240  WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) +
241  "' to '" + to->getLaneID(toLane) + "'.");
242  } else {
243  from = nFrom;
244  }
245  }
246  } catch (NumberFormatException&) {
247  myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
248  }
249  //
250  bool keepUncontrolled = attrs.getOptBoolReporting(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
251  if (keepUncontrolled) {
252  from->disableConnection4TLS(fromLane, to, toLane);
253  }
254 }
255 
256 bool
258  int* fromLane, int* toLane) {
259  if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
260  return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
261  } else {
262  return parseLaneDefinition(attributes, fromLane, toLane);
263  }
264 }
265 
266 
267 inline bool
269  NBEdge* from, NBEdge* to,
270  int* fromLane, int* toLane) {
271  bool ok = true;
274  WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
276  "' instead.");
277  }
278 
279  std::string laneConn = attributes.getStringReporting(SUMO_ATTR_LANE, 0, ok);
280  StringTokenizer st(laneConn, ':');
281  if (!ok || st.size() != 2) {
282  myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
283  from->getID() + "' to '" + to->getID() + "'.");
284  return false; // There was an error.
285  }
286 
287  *fromLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1);
288  *toLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1);
289 
290  return true; // We succeeded.
291 }
292 
293 
294 inline bool
296  int* fromLane,
297  int* toLane) {
298  bool ok = true;
299  *fromLane = attributes.getIntReporting(SUMO_ATTR_FROM_LANE, 0, ok);
300  *toLane = attributes.getIntReporting(SUMO_ATTR_TO_LANE, 0, ok);
301  return ok;
302 }
303 
304 
305 bool
306 NIXMLConnectionsHandler::validateLaneInfo(bool canLanesBeNegative, NBEdge* fromEdge, NBEdge* toEdge, int fromLane, int toLane) {
307  if ((!canLanesBeNegative && fromLane < 0) ||
308  static_cast<unsigned int>(fromLane) >= fromEdge->getNumLanes()) {
309  myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
310  "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
311  fromEdge->getID() + "' to '" + toEdge->getID() + "'.");
312  return false;
313  }
314  if ((!canLanesBeNegative && toLane < 0) ||
315  static_cast<unsigned int>(toLane) >= toEdge->getNumLanes()) {
316  myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
317  "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
318  fromEdge->getID() + "' to '" + toEdge->getID() + "'.");
319  return false;
320  }
321  return true;
322 }
323 
324 /****************************************************************************/
325