1 package org.opentrafficsim.core.network;
2
3 import java.io.Serializable;
4 import java.rmi.RemoteException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import javax.naming.Binding;
14 import javax.naming.NamingEnumeration;
15 import javax.naming.NamingException;
16 import javax.naming.event.EventContext;
17
18 import org.jgrapht.GraphPath;
19 import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
20 import org.jgrapht.graph.SimpleDirectedWeightedGraph;
21 import org.opentrafficsim.core.animation.ClonableRenderable2DInterface;
22 import org.opentrafficsim.core.gtu.GTU;
23 import org.opentrafficsim.core.gtu.GTUType;
24 import org.opentrafficsim.core.network.route.CompleteRoute;
25 import org.opentrafficsim.core.network.route.Route;
26 import org.opentrafficsim.core.object.InvisibleObjectInterface;
27 import org.opentrafficsim.core.object.ObjectInterface;
28 import org.opentrafficsim.core.perception.PerceivableContext;
29
30 import nl.tudelft.simulation.dsol.animation.Locatable;
31 import nl.tudelft.simulation.dsol.animation.D2.Renderable2DInterface;
32 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
33 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
34 import nl.tudelft.simulation.event.EventProducer;
35 import nl.tudelft.simulation.immutablecollections.Immutable;
36 import nl.tudelft.simulation.immutablecollections.ImmutableHashMap;
37 import nl.tudelft.simulation.immutablecollections.ImmutableMap;
38 import nl.tudelft.simulation.naming.context.ContextUtil;
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class OTSNetwork extends EventProducer implements Network, PerceivableContext, Serializable
53 {
54
55 private static final long serialVersionUID = 20150722;
56
57
58 private final String id;
59
60
61 private Map<String, Node> nodeMap = new HashMap<>();
62
63
64 private Map<String, Link> linkMap = new HashMap<>();
65
66
67 private Map<String, ObjectInterface> objectMap = new HashMap<>();
68
69
70 private Map<String, InvisibleObjectInterface> invisibleObjectMap = new HashMap<>();
71
72
73 private Map<GTUType, Map<String, Route>> routeMap = new HashMap<>();
74
75
76 private Map<GTUType, SimpleDirectedWeightedGraph<Node, LinkEdge<Link>>> linkGraphs = new HashMap<>();
77
78
79 private Map<String, GTU> gtuMap = new HashMap<>();
80
81
82
83
84
85 public OTSNetwork(final String id)
86 {
87 this.id = id;
88 }
89
90
91 @Override
92 public final String getId()
93 {
94 return this.id;
95 }
96
97
98
99
100
101
102 @Override
103 public final ImmutableMap<String, Node> getNodeMap()
104 {
105 return new ImmutableHashMap<>(this.nodeMap, Immutable.WRAP);
106 }
107
108
109 @Override
110 public final void addNode(final Node node) throws NetworkException
111 {
112 if (containsNode(node))
113 {
114 throw new NetworkException("Node " + node + " already registered in network " + this.id);
115 }
116 if (this.nodeMap.keySet().contains(node.getId()))
117 {
118 throw new NetworkException("Node with name " + node.getId() + " already registered in network " + this.id);
119 }
120 this.nodeMap.put(node.getId(), node);
121 fireEvent(Network.NODE_ADD_EVENT, node.getId());
122 }
123
124
125 @Override
126 public final void removeNode(final Node node) throws NetworkException
127 {
128 if (!containsNode(node))
129 {
130 throw new NetworkException("Node " + node + " not registered in network " + this.id);
131 }
132 fireEvent(Network.NODE_REMOVE_EVENT, node.getId());
133 this.nodeMap.remove(node.getId());
134 }
135
136
137 @Override
138 public final boolean containsNode(final Node node)
139 {
140
141 return this.nodeMap.keySet().contains(node.getId());
142 }
143
144
145 @Override
146 public final boolean containsNode(final String nodeId)
147 {
148 return this.nodeMap.keySet().contains(nodeId);
149 }
150
151
152 @Override
153 public final Node getNode(final String nodeId)
154 {
155 return this.nodeMap.get(nodeId);
156 }
157
158
159
160
161
162
163 @Override
164 public final ImmutableMap<String, Link> getLinkMap()
165 {
166 return new ImmutableHashMap<>(this.linkMap, Immutable.WRAP);
167 }
168
169
170 @Override
171 public final void addLink(final Link link) throws NetworkException
172 {
173 if (containsLink(link))
174 {
175 throw new NetworkException("Link " + link + " already registered in network " + this.id);
176 }
177 if (this.linkMap.keySet().contains(link.getId()))
178 {
179 throw new NetworkException("Link with name " + link.getId() + " already registered in network " + this.id);
180 }
181 if (!containsNode(link.getStartNode()) || !containsNode(link.getEndNode()))
182 {
183 throw new NetworkException(
184 "Start node or end node of Link " + link.getId() + " not registered in network " + this.id);
185 }
186 this.linkMap.put(link.getId(), link);
187 fireEvent(Network.LINK_ADD_EVENT, link.getId());
188 }
189
190
191 @Override
192 public final void removeLink(final Link link) throws NetworkException
193 {
194 if (!containsLink(link))
195 {
196 throw new NetworkException("Link " + link + " not registered in network " + this.id);
197 }
198 fireEvent(Network.LINK_REMOVE_EVENT, link.getId());
199 this.linkMap.remove(link.getId());
200 }
201
202
203 @Override
204 public final Link getLink(final Node node1, final Node node2)
205 {
206 for (Link link : this.linkMap.values())
207 {
208 if (link.getStartNode().equals(node1) && link.getEndNode().equals(node2))
209 {
210 return link;
211 }
212 }
213 return null;
214 }
215
216
217 @Override
218 public final Link getLink(final String nodeId1, final String nodeId2) throws NetworkException
219 {
220 if (!containsNode(nodeId1))
221 {
222 throw new NetworkException("Node " + nodeId1 + " not in network " + this.id);
223 }
224 if (!containsNode(nodeId2))
225 {
226 throw new NetworkException("Node " + nodeId2 + " not in network " + this.id);
227 }
228 return getLink(getNode(nodeId1), getNode(nodeId2));
229 }
230
231
232 @Override
233 public final boolean containsLink(final Link link)
234 {
235 return this.linkMap.keySet().contains(link.getId());
236 }
237
238
239 @Override
240 public final boolean containsLink(final String linkId)
241 {
242 return this.linkMap.keySet().contains(linkId);
243 }
244
245
246 @Override
247 public final Link getLink(final String linkId)
248 {
249 return this.linkMap.get(linkId);
250 }
251
252
253
254
255
256
257 @Override
258 public final ImmutableMap<String, ObjectInterface> getObjectMap()
259 {
260 return new ImmutableHashMap<>(this.objectMap, Immutable.WRAP);
261 }
262
263
264 @SuppressWarnings("unchecked")
265 @Override
266 public final <T extends ObjectInterface> ImmutableMap<String, T> getObjectMap(final Class<T> objectType)
267 {
268 Map<String, T> result = new HashMap<>();
269 for (String key : this.objectMap.keySet())
270 {
271 ObjectInterface o = this.objectMap.get(key);
272 if (objectType.isInstance(o))
273 {
274 result.put(key, (T) o);
275 }
276 }
277 return new ImmutableHashMap<>(result, Immutable.WRAP);
278 }
279
280
281 @Override
282 public final void addObject(final ObjectInterface object) throws NetworkException
283 {
284 if (containsObject(object))
285 {
286 throw new NetworkException("Object " + object + " already registered in network " + this.id);
287 }
288 if (containsObject(object.getFullId()))
289 {
290 throw new NetworkException("Object with name " + object.getFullId() + " already registered in network " + this.id);
291 }
292 this.objectMap.put(object.getFullId(), object);
293 fireEvent(Network.OBJECT_ADD_EVENT, object.getFullId());
294 }
295
296
297 @Override
298 public final void removeObject(final ObjectInterface object) throws NetworkException
299 {
300 if (!containsObject(object))
301 {
302 throw new NetworkException("Object " + object + " not registered in network " + this.id);
303 }
304 fireEvent(Network.OBJECT_REMOVE_EVENT, object.getFullId());
305 this.objectMap.remove(object.getFullId());
306 }
307
308
309 @Override
310 public final boolean containsObject(final ObjectInterface object)
311 {
312 return this.objectMap.containsKey(object.getFullId());
313 }
314
315
316
317
318
319
320
321 @Override
322 public final boolean containsObject(final String objectId)
323 {
324 return this.objectMap.containsKey(objectId);
325 }
326
327
328
329
330
331
332 @Override
333 public final ImmutableMap<String, InvisibleObjectInterface> getInvisibleObjectMap()
334 {
335 return new ImmutableHashMap<>(this.invisibleObjectMap, Immutable.WRAP);
336 }
337
338
339 @Override
340 public final ImmutableMap<String, InvisibleObjectInterface> getInvisibleObjectMap(
341 final Class<InvisibleObjectInterface> objectType)
342 {
343 Map<String, InvisibleObjectInterface> result = new HashMap<>();
344 for (String key : this.objectMap.keySet())
345 {
346 InvisibleObjectInterface o = this.invisibleObjectMap.get(key);
347 if (objectType.isInstance(o))
348 {
349 result.put(key, o);
350 }
351 }
352 return new ImmutableHashMap<>(result, Immutable.WRAP);
353 }
354
355
356 @Override
357 public final void addInvisibleObject(final InvisibleObjectInterface object) throws NetworkException
358 {
359 if (containsInvisibleObject(object))
360 {
361 throw new NetworkException("InvisibleObject " + object + " already registered in network " + this.id);
362 }
363 if (containsInvisibleObject(object.getFullId()))
364 {
365 throw new NetworkException(
366 "InvisibleObject with name " + object.getFullId() + " already registered in network " + this.id);
367 }
368 this.invisibleObjectMap.put(object.getFullId(), object);
369 fireEvent(Network.INVISIBLE_OBJECT_ADD_EVENT, object.getFullId());
370 }
371
372
373 @Override
374 public final void removeInvisibleObject(final InvisibleObjectInterface object) throws NetworkException
375 {
376 if (!containsInvisibleObject(object))
377 {
378 throw new NetworkException("InvisibleObject " + object + " not registered in network " + this.id);
379 }
380 fireEvent(Network.INVISIBLE_OBJECT_REMOVE_EVENT, object.getFullId());
381 this.objectMap.remove(object.getFullId());
382 }
383
384
385 @Override
386 public final boolean containsInvisibleObject(final InvisibleObjectInterface object)
387 {
388 return this.invisibleObjectMap.containsKey(object.getFullId());
389 }
390
391
392
393
394
395
396
397 @Override
398 public final boolean containsInvisibleObject(final String objectId)
399 {
400 return this.invisibleObjectMap.containsKey(objectId);
401 }
402
403
404
405
406
407
408 @Override
409 public final ImmutableMap<String, Route> getDefinedRouteMap(final GTUType gtuType)
410 {
411 Map<String, Route> routes = new HashMap<>();
412 if (this.routeMap.containsKey(gtuType))
413 {
414 routes.putAll(this.routeMap.get(gtuType));
415 }
416 return new ImmutableHashMap<>(routes, Immutable.WRAP);
417 }
418
419
420 @Override
421 public final void addRoute(final GTUType gtuType, final Route route) throws NetworkException
422 {
423 if (containsRoute(gtuType, route))
424 {
425 throw new NetworkException(
426 "Route " + route + " for GTUType " + gtuType + " already registered in network " + this.id);
427 }
428 if (this.routeMap.containsKey(gtuType) && this.routeMap.get(gtuType).keySet().contains(route.getId()))
429 {
430 throw new NetworkException("Route with name " + route.getId() + " for GTUType " + gtuType
431 + " already registered in network " + this.id);
432 }
433 for (Node node : route.getNodes())
434 {
435 if (!containsNode(node))
436 {
437 throw new NetworkException("Node " + node.getId() + " of route " + route.getId() + " for GTUType " + gtuType
438 + " not registered in network " + this.id);
439 }
440 }
441 if (!this.routeMap.containsKey(gtuType))
442 {
443 this.routeMap.put(gtuType, new HashMap<String, Route>());
444 }
445 this.routeMap.get(gtuType).put(route.getId(), route);
446 fireEvent(Network.ROUTE_ADD_EVENT, new Object[] { gtuType.getId(), route.getId() });
447 }
448
449
450 @Override
451 public final void removeRoute(final GTUType gtuType, final Route route) throws NetworkException
452 {
453 if (!containsRoute(gtuType, route))
454 {
455 throw new NetworkException("Route " + route + " for GTUType " + gtuType + " not registered in network " + this.id);
456 }
457 fireEvent(Network.ROUTE_REMOVE_EVENT, new Object[] { gtuType.getId(), route.getId() });
458 this.routeMap.get(gtuType).remove(route.getId());
459 }
460
461
462 @Override
463 public final boolean containsRoute(final GTUType gtuType, final Route route)
464 {
465 if (this.routeMap.containsKey(gtuType))
466 {
467 return this.routeMap.get(gtuType).values().contains(route);
468 }
469 return false;
470 }
471
472
473 @Override
474 public final boolean containsRoute(final GTUType gtuType, final String routeId)
475 {
476 if (this.routeMap.containsKey(gtuType))
477 {
478 return this.routeMap.get(gtuType).keySet().contains(routeId);
479 }
480 return false;
481 }
482
483
484
485
486
487
488 public final Route getRoute(final String routeId)
489 {
490 for (GTUType gtuType : this.routeMap.keySet())
491 {
492 Route route = this.routeMap.get(gtuType).get(routeId);
493 if (route != null)
494 {
495 return route;
496 }
497 }
498 return null;
499 }
500
501
502 @Override
503 public final Route getRoute(final GTUType gtuType, final String routeId)
504 {
505 if (this.routeMap.containsKey(gtuType))
506 {
507 return this.routeMap.get(gtuType).get(routeId);
508 }
509 return null;
510 }
511
512
513 @Override
514 public final Set<Route> getRoutesBetween(final GTUType gtuType, final Node nodeFrom, final Node nodeTo)
515 {
516 Set<Route> routes = new LinkedHashSet<>();
517 if (this.routeMap.containsKey(gtuType))
518 {
519 for (Route route : this.routeMap.get(gtuType).values())
520 {
521 try
522 {
523 if (route.originNode().equals(nodeFrom) && route.destinationNode().equals(nodeTo))
524 {
525 routes.add(route);
526 }
527 }
528 catch (@SuppressWarnings("unused") NetworkException ne)
529 {
530
531 }
532 }
533 }
534 return routes;
535 }
536
537
538 @Override
539 public final void buildGraph(final GTUType gtuType)
540 {
541 SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> graph = buildGraph(gtuType, LinkWeight.LENGTH);
542 this.linkGraphs.put(gtuType, graph);
543 }
544
545
546
547
548
549
550
551 private SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> buildGraph(final GTUType gtuType, final LinkWeight linkWeight)
552 {
553
554 @SuppressWarnings({ "unchecked" })
555
556 Class<LinkEdge<Link>> linkEdgeClass = (Class<LinkEdge<Link>>) new LinkEdge<OTSLink>(null).getClass();
557 SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> graph = new SimpleDirectedWeightedGraph<>(linkEdgeClass);
558 for (Node node : this.nodeMap.values())
559 {
560 graph.addVertex(node);
561 }
562 for (Link link : this.linkMap.values())
563 {
564
565 LongitudinalDirectionality directionality = link.getDirectionality(gtuType);
566 if (directionality.isForwardOrBoth())
567 {
568 LinkEdge<Link> linkEdge = new LinkEdge<>(link);
569 graph.addEdge(link.getStartNode(), link.getEndNode(), linkEdge);
570 graph.setEdgeWeight(linkEdge, linkWeight.getWeight(link));
571 }
572 if (directionality.isBackwardOrBoth())
573 {
574 LinkEdge<Link> linkEdge = new LinkEdge<>(link);
575 graph.addEdge(link.getEndNode(), link.getStartNode(), linkEdge);
576 graph.setEdgeWeight(linkEdge, linkWeight.getWeight(link));
577 }
578 }
579 return graph;
580 }
581
582
583 @Override
584 public final CompleteRoute getShortestRouteBetween(final GTUType gtuType, final Node nodeFrom, final Node nodeTo,
585 final LinkWeight linkWeight) throws NetworkException
586 {
587 CompleteRoute route = new CompleteRoute("Route for " + gtuType + " from " + nodeFrom + "to " + nodeTo, gtuType);
588 SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> graph = getGraph(gtuType, linkWeight);
589
590
591 GraphPath<Node, LinkEdge<Link>> path = DijkstraShortestPath.findPathBetween(graph, nodeFrom, nodeTo);
592 if (path == null)
593 {
594 return null;
595 }
596 route.addNode(nodeFrom);
597 for (LinkEdge<Link> link : path.getEdgeList())
598 {
599 if (!link.getLink().getEndNode().equals(route.destinationNode())
600 && route.destinationNode().isDirectionallyConnectedTo(gtuType, link.getLink().getEndNode()))
601 {
602 route.addNode(link.getLink().getEndNode());
603 }
604 else if (!link.getLink().getStartNode().equals(route.destinationNode())
605 && route.destinationNode().isDirectionallyConnectedTo(gtuType, link.getLink().getStartNode()))
606 {
607 route.addNode(link.getLink().getStartNode());
608 }
609 else
610 {
611 throw new NetworkException("Cannot connect two links when calculating shortest route");
612 }
613 }
614 return route;
615 }
616
617
618 @Override
619 public final CompleteRoute getShortestRouteBetween(final GTUType gtuType, final Node nodeFrom, final Node nodeTo,
620 final List<Node> nodesVia) throws NetworkException
621 {
622 return getShortestRouteBetween(gtuType, nodeFrom, nodeTo, nodesVia, LinkWeight.LENGTH);
623 }
624
625
626 @Override
627 public final CompleteRoute getShortestRouteBetween(final GTUType gtuType, final Node nodeFrom, final Node nodeTo,
628 final List<Node> nodesVia, final LinkWeight linkWeight) throws NetworkException
629 {
630 CompleteRoute route = new CompleteRoute(
631 "Route for " + gtuType + " from " + nodeFrom + "to " + nodeTo + " via " + nodesVia.toString(), gtuType);
632 SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> graph = getGraph(gtuType, linkWeight);
633 List<Node> nodes = new ArrayList<>();
634 nodes.add(nodeFrom);
635 nodes.addAll(nodesVia);
636 nodes.add(nodeTo);
637 Node from = nodeFrom;
638 route.addNode(nodeFrom);
639 for (int i = 1; i < nodes.size(); i++)
640 {
641 Node to = nodes.get(i);
642 DijkstraShortestPath<Node, LinkEdge<Link>> dijkstra = new DijkstraShortestPath<>(graph);
643 GraphPath<Node, LinkEdge<Link>> path = dijkstra.getPath(from, to);
644 if (path == null)
645 {
646 return null;
647 }
648 for (LinkEdge<Link> link : path.getEdgeList())
649 {
650 if (!link.getLink().getEndNode().equals(route.destinationNode())
651 && route.destinationNode().isDirectionallyConnectedTo(gtuType, link.getLink().getEndNode()))
652 {
653 route.addNode(link.getLink().getEndNode());
654 }
655 else if (!link.getLink().getStartNode().equals(route.destinationNode())
656 && route.destinationNode().isDirectionallyConnectedTo(gtuType, link.getLink().getStartNode()))
657 {
658 route.addNode(link.getLink().getStartNode());
659 }
660 else
661 {
662 throw new NetworkException(
663 "Cannot connect two links when calculating shortest route with intermediate nodes");
664 }
665 }
666 from = to;
667 }
668 return route;
669 }
670
671
672
673
674
675
676
677 private SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> getGraph(final GTUType gtuType, final LinkWeight linkWeight)
678 {
679 SimpleDirectedWeightedGraph<Node, LinkEdge<Link>> graph;
680 if (linkWeight.equals(LinkWeight.LENGTH))
681 {
682
683 if (!this.linkGraphs.containsKey(gtuType))
684 {
685 buildGraph(gtuType);
686 }
687 graph = this.linkGraphs.get(gtuType);
688 }
689 else
690 {
691 graph = buildGraph(gtuType, linkWeight);
692 }
693 return graph;
694 }
695
696
697
698
699
700
701 @Override
702 public final void addGTU(final GTU gtu)
703 {
704 this.gtuMap.put(gtu.getId(), gtu);
705 fireTimedEvent(Network.GTU_ADD_EVENT, gtu.getId(), gtu.getSimulator().getSimulatorTime());
706 }
707
708
709 @Override
710 public final void removeGTU(final GTU gtu)
711 {
712 fireTimedEvent(Network.GTU_REMOVE_EVENT, gtu.getId(), gtu.getSimulator().getSimulatorTime());
713 this.gtuMap.remove(gtu.getId());
714 }
715
716
717 @Override
718 public final boolean containsGTU(final GTU gtu)
719 {
720 return this.gtuMap.containsValue(gtu);
721 }
722
723
724 @Override
725 public final GTU getGTU(final String gtuId)
726 {
727 return this.gtuMap.get(gtuId);
728 }
729
730
731 @Override
732 public final Set<GTU> getGTUs()
733 {
734
735 return new HashSet<>(this.gtuMap.values());
736 }
737
738
739 @Override
740 public final boolean containsGtuId(final String gtuId)
741 {
742 return this.gtuMap.containsKey(gtuId);
743 }
744
745
746 @Override
747 public final String toString()
748 {
749 return "OTSNetwork [id=" + this.id + ", nodeMapSize=" + this.nodeMap.size() + ", linkMapSize=" + this.linkMap.size()
750 + ", objectMapSize=" + this.objectMap.size() + ", routeMapSize=" + this.routeMap.size() + ", gtuMapSize="
751 + this.gtuMap.size() + "]";
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767 @SuppressWarnings("checkstyle:designforextension")
768 public OTSNetwork clone(final String newId, final SimulatorInterface.TimeDoubleUnit oldSimulator,
769 final SimulatorInterface.TimeDoubleUnit newSimulator, final boolean animation) throws NetworkException
770 {
771 OTSNetwork newNetwork = new OTSNetwork(newId);
772
773
774 for (Node node : this.nodeMap.values())
775 {
776 ((OTSNode) node).clone1(newNetwork, newSimulator);
777 }
778
779
780 for (Link oldLink : this.linkMap.values())
781 {
782 OTSLink newLink = ((OTSLink) oldLink).clone(newNetwork, newSimulator, animation);
783 if (animation)
784 {
785 cloneAnimation(oldLink, newLink, oldSimulator, newSimulator);
786 }
787 }
788
789
790 for (Node oldNode : this.nodeMap.values())
791 {
792 OTSNode newNode = ((OTSNode) oldNode).clone2(newNetwork, newSimulator, animation);
793 if (animation)
794 {
795 cloneAnimation(oldNode, newNode, oldSimulator, newSimulator);
796 }
797 }
798
799
800 for (GTUType gtuType : this.linkGraphs.keySet())
801 {
802 newNetwork.buildGraph(gtuType);
803 }
804
805
806 Map<GTUType, Map<String, Route>> newRouteMap = new HashMap<>();
807 for (GTUType gtuType : this.routeMap.keySet())
808 {
809 Map<String, Route> newRoutes = new HashMap<>();
810 for (Route route : this.routeMap.get(gtuType).values())
811 {
812 newRoutes.put(route.getId(), route.clone(newNetwork, newSimulator, animation));
813 }
814 newRouteMap.put(gtuType, newRoutes);
815 }
816 newNetwork.routeMap = newRouteMap;
817
818 for (InvisibleObjectInterface io : getInvisibleObjectMap().values())
819 {
820 InvisibleObjectInterface clonedIO = io.clone(newSimulator, newNetwork);
821 newNetwork.addInvisibleObject(clonedIO);
822 }
823 return newNetwork;
824 }
825
826
827
828
829
830
831
832
833
834
835
836
837 @SuppressWarnings("checkstyle:designforextension")
838 public static <T extends Locatable> void cloneAnimation(final Locatable oldSource, final T newSource,
839 final SimulatorInterface.TimeDoubleUnit oldSimulator, final SimulatorInterface.TimeDoubleUnit newSimulator)
840 {
841 if (!(oldSimulator instanceof AnimatorInterface) || !(newSimulator instanceof AnimatorInterface))
842 {
843 return;
844 }
845
846 try
847 {
848 EventContext context =
849 (EventContext) ContextUtil.lookup(oldSimulator.getReplication().getContext(), "/animation/2D");
850 NamingEnumeration<Binding> list = context.listBindings("");
851 while (list.hasMore())
852 {
853 Binding binding = list.next();
854 @SuppressWarnings("unchecked")
855 Renderable2DInterface<T> animationObject = (Renderable2DInterface<T>) binding.getObject();
856 T locatable = animationObject.getSource();
857 if (oldSource.equals(locatable) && animationObject instanceof ClonableRenderable2DInterface)
858 {
859 ((ClonableRenderable2DInterface<T>) animationObject).clone(newSource, newSimulator);
860 }
861 }
862 }
863 catch (@SuppressWarnings("unused") NamingException | RemoteException exception)
864 {
865 System.err.println("Error when cloning animation objects for object " + oldSource);
866 }
867 }
868
869
870
871
872
873 @SuppressWarnings("checkstyle:designforextension")
874 public void destroy(final SimulatorInterface.TimeDoubleUnit simulator)
875 {
876 for (GTU gtu : this.getGTUs())
877 {
878 gtu.destroy();
879 }
880
881 Set<Renderable2DInterface<?>> animationObjects = new HashSet<>();
882 try
883 {
884 EventContext context = (EventContext) ContextUtil.lookup(simulator.getReplication().getContext(), "/animation/2D");
885 NamingEnumeration<Binding> list = context.listBindings("");
886 while (list.hasMore())
887 {
888 Binding binding = list.next();
889 Renderable2DInterface<?> animationObject = (Renderable2DInterface<?>) binding.getObject();
890 animationObjects.add(animationObject);
891 }
892
893 for (Renderable2DInterface<?> ao : animationObjects)
894 {
895 try
896 {
897 ao.destroy();
898 }
899 catch (Exception e)
900 {
901
902 }
903 }
904 }
905 catch (NamingException exception)
906 {
907 System.err.println("Error when destroying animation objects");
908 }
909
910 this.nodeMap.clear();
911 this.linkMap.clear();
912 this.linkGraphs.clear();
913 this.routeMap.clear();
914 }
915
916
917
918
919
920
921 @SuppressWarnings("checkstyle:designforextension")
922 public void removeAnimation(final Class<?> clazz, final SimulatorInterface.TimeDoubleUnit oldSimulator)
923 {
924 if (!(oldSimulator instanceof AnimatorInterface))
925 {
926 return;
927 }
928
929 try
930 {
931 EventContext context =
932 (EventContext) ContextUtil.lookup(oldSimulator.getReplication().getContext(), "/animation/2D");
933 NamingEnumeration<Binding> list = context.listBindings("");
934 while (list.hasMore())
935 {
936 Binding binding = list.next();
937 Renderable2DInterface<?> animationObject = (Renderable2DInterface<?>) binding.getObject();
938 Locatable locatable = animationObject.getSource();
939 if (clazz.isAssignableFrom(locatable.getClass()))
940 {
941 animationObject.destroy();
942 }
943 }
944 }
945 catch (@SuppressWarnings("unused") NamingException | RemoteException exception)
946 {
947 System.err.println("Error when destroying animation objects for class " + clazz.getSimpleName());
948 }
949 }
950
951 }