MySourceBase.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  1. /*This is a modified version of the class org.graphstream.stream.SourceBase
  2. * It was modified by Jascha Bohne <jaschabohne@web.de> for use in the scopviz project
  3. * This class is based on the 1.3 release of graphstream
  4. *
  5. * Copyright 2006 - 2015
  6. * Stefan Balev <stefan.balev@graphstream-project.org>
  7. * Julien Baudry <julien.baudry@graphstream-project.org>
  8. * Antoine Dutot <antoine.dutot@graphstream-project.org>
  9. * Yoann Pigné <yoann.pigne@graphstream-project.org>
  10. * Guilhelm Savin <guilhelm.savin@graphstream-project.org>
  11. *
  12. * This file is part of GraphStream <http://graphstream-project.org>.
  13. *
  14. * GraphStream is a library whose purpose is to handle static or dynamic
  15. * graph, create them from scratch, file or any source and display them.
  16. *
  17. * This program is free software distributed under the terms of two licenses, the
  18. * CeCILL-C license that fits European law, and the GNU Lesser General Public
  19. * License. You can use, modify and/ or redistribute the software under the terms
  20. * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
  21. * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
  22. * the Free Software Foundation, either version 3 of the License, or (at your
  23. * option) any later version.
  24. *
  25. * This program is distributed in the hope that it will be useful, but WITHOUT ANY
  26. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  27. * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU Lesser General Public License
  30. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  31. *
  32. * The fact that you are presently reading this means that you have had
  33. * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
  34. */
  35. package de.tu_darmstadt.informatik.tk.scopviz.io;
  36. import java.util.ArrayList;
  37. import java.util.LinkedList;
  38. import java.util.List;
  39. import java.util.Stack;
  40. import org.graphstream.graph.implementations.AbstractElement.AttributeChangeEvent;
  41. import org.graphstream.stream.AttributeSink;
  42. import org.graphstream.stream.ElementSink;
  43. import org.graphstream.stream.Sink;
  44. import org.graphstream.stream.Source;
  45. import org.graphstream.stream.sync.SourceTime;
  46. import de.tu_darmstadt.informatik.tk.scopviz.debug.Debug;
  47. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyGraph;
  48. /**
  49. * Base implementation of an input that provide basic sink handling.
  50. *
  51. * <p>
  52. * This implementation can register a set of graph sinks (or separate sets of
  53. * attributes or elements sinks) and provides protected methods to easily
  54. * broadcast events to all the sinks (beginning with "send").
  55. * </p>
  56. *
  57. * <p>
  58. * Each time you want to produce an event toward all registered sinks, you call
  59. * one of the "send*" methods with correct parameters. The parameters of the
  60. * "send*" methods maps to the usual GraphStream events.
  61. * </p>
  62. *
  63. * <p>
  64. * This class is "reentrant". This means that if a send*() method is called
  65. * during the execution of another or the same send*() method, the event is
  66. * deferred until the first send*() method is finished. This avoid recursive
  67. * loops if a sink modifies the input during event handling.
  68. * </p>
  69. */
  70. public class MySourceBase implements Source {
  71. // Attribute
  72. /**
  73. * if the programm is currently reading a multigraph
  74. */
  75. protected boolean multiGraph = false;
  76. /**
  77. * @return if the last read Graph was a multigraph
  78. */
  79. public boolean wasMultiGraph() {
  80. return multiGraph;
  81. }
  82. /**
  83. * the sink of the complete Graph
  84. */
  85. protected Sink originalSink;
  86. /**
  87. * Enum of the different possible Types of Elements.
  88. */
  89. public enum ElementType {
  90. NODE, EDGE, GRAPH
  91. };
  92. /**
  93. * Set of graph attributes sinks.
  94. */
  95. protected ArrayList<AttributeSink> attrSinks = new ArrayList<AttributeSink>();
  96. /**
  97. * Set of graph elements sinks.
  98. */
  99. protected ArrayList<ElementSink> eltsSinks = new ArrayList<ElementSink>();
  100. /**
  101. * A queue that allow the management of events (nodes/edge
  102. * add/delete/change) in the right order.
  103. */
  104. protected LinkedList<GraphEvent> eventQueue = new LinkedList<GraphEvent>();
  105. /**
  106. * A boolean that indicates whether or not an Sink event is being sent
  107. * during another one.
  108. */
  109. protected boolean eventProcessing = false;
  110. /**
  111. * Id of this source.
  112. */
  113. protected String sourceId;
  114. /**
  115. * Time of this source.
  116. */
  117. protected SourceTime sourceTime;
  118. /**
  119. * a List of all inner Graphs of a multigraphFile.
  120. */
  121. protected LinkedList<MyGraph> subGraphs = new LinkedList<>();
  122. /**
  123. * all inner graphs that are currently being edited.
  124. */
  125. protected Stack<MyGraph> usedSubGraphs = new Stack<>();
  126. /**
  127. * the ID of the (last added) outer Graph.
  128. */
  129. protected String superID = "";
  130. // Construction
  131. /**
  132. * Creates a new MySourceBase Object with a random ID.
  133. */
  134. protected MySourceBase() {
  135. this(String.format("sourceOnThread#%d_%d", Thread.currentThread().getId(),
  136. System.currentTimeMillis() + ((int) (Math.random() * 1000))));
  137. }
  138. /**
  139. * Creates a new MySourceBase Object with a given ID.
  140. *
  141. * @param sourceId
  142. * the ID to use
  143. */
  144. protected MySourceBase(String sourceId) {
  145. this.sourceId = sourceId;
  146. this.sourceTime = new SourceTime(sourceId);
  147. }
  148. // Access
  149. /**
  150. * Returns an Iterable over all the attribute sinks.
  151. *
  152. * @return the Iterable
  153. */
  154. public Iterable<AttributeSink> attributeSinks() {
  155. return attrSinks;
  156. }
  157. /**
  158. * Returns an Iterable over all the element sinks.
  159. *
  160. * @return the Iterable
  161. */
  162. public Iterable<ElementSink> elementSinks() {
  163. return eltsSinks;
  164. }
  165. // Command
  166. @Override
  167. public void addSink(Sink sink) {
  168. multiGraph = false;
  169. originalSink = sink;
  170. addAttributeSink(sink);
  171. addElementSink(sink);
  172. resetSubGraphs();
  173. try {
  174. superID = ((MyGraph) sink).getId();
  175. } catch (Exception e) {
  176. Debug.out(e.toString() + "\n" + e.getStackTrace().toString());
  177. }
  178. }
  179. /**
  180. * Adds a new Sink that works with SubGraphs.
  181. *
  182. * @param sink
  183. * the Sink to add
  184. */
  185. private void addSubGraphSink(Sink sink) {
  186. addAttributeSink(sink);
  187. addElementSink(sink);
  188. }
  189. @Override
  190. public void addAttributeSink(AttributeSink sink) {
  191. if (!eventProcessing) {
  192. eventProcessing = true;
  193. manageEvents();
  194. attrSinks.add(sink);
  195. manageEvents();
  196. eventProcessing = false;
  197. } else {
  198. eventQueue.add(new AddToListEvent<AttributeSink>(attrSinks, sink));
  199. }
  200. }
  201. @Override
  202. public void addElementSink(ElementSink sink) {
  203. if (!eventProcessing) {
  204. eventProcessing = true;
  205. manageEvents();
  206. eltsSinks.add(sink);
  207. manageEvents();
  208. eventProcessing = false;
  209. } else {
  210. eventQueue.add(new AddToListEvent<ElementSink>(eltsSinks, sink));
  211. }
  212. }
  213. @Override
  214. public void clearSinks() {
  215. clearElementSinks();
  216. clearAttributeSinks();
  217. }
  218. @Override
  219. public void clearElementSinks() {
  220. if (!eventProcessing) {
  221. eventProcessing = true;
  222. manageEvents();
  223. eltsSinks.clear();
  224. manageEvents();
  225. eventProcessing = false;
  226. } else {
  227. eventQueue.add(new ClearListEvent<ElementSink>(eltsSinks));
  228. }
  229. }
  230. @Override
  231. public void clearAttributeSinks() {
  232. if (!eventProcessing) {
  233. eventProcessing = true;
  234. manageEvents();
  235. attrSinks.clear();
  236. manageEvents();
  237. eventProcessing = false;
  238. } else {
  239. eventQueue.add(new ClearListEvent<AttributeSink>(attrSinks));
  240. }
  241. }
  242. @Override
  243. public void removeSink(Sink sink) {
  244. removeAttributeSink(sink);
  245. removeElementSink(sink);
  246. }
  247. @Override
  248. public void removeAttributeSink(AttributeSink sink) {
  249. if (!eventProcessing) {
  250. eventProcessing = true;
  251. manageEvents();
  252. attrSinks.remove(sink);
  253. manageEvents();
  254. eventProcessing = false;
  255. } else {
  256. eventQueue.add(new RemoveFromListEvent<AttributeSink>(attrSinks, sink));
  257. }
  258. }
  259. @Override
  260. public void removeElementSink(ElementSink sink) {
  261. if (!eventProcessing) {
  262. eventProcessing = true;
  263. manageEvents();
  264. eltsSinks.remove(sink);
  265. manageEvents();
  266. eventProcessing = false;
  267. } else {
  268. eventQueue.add(new RemoveFromListEvent<ElementSink>(eltsSinks, sink));
  269. }
  270. }
  271. /**
  272. * Send a "graph cleared" event to all element sinks.
  273. *
  274. * @param sourceId
  275. * The source identifier.
  276. */
  277. public void sendGraphCleared(String sourceId) {
  278. sendGraphCleared(sourceId, sourceTime.newEvent());
  279. }
  280. /**
  281. * Send a "graph cleared" event to all element sinks.
  282. *
  283. * @param sourceId
  284. * The source identifier.
  285. * @param timeId
  286. */
  287. public void sendGraphCleared(String sourceId, long timeId) {
  288. if (!eventProcessing) {
  289. eventProcessing = true;
  290. manageEvents();
  291. for (int i = 0; i < eltsSinks.size(); i++) {
  292. eltsSinks.get(i).graphCleared(sourceId, timeId);
  293. }
  294. manageEvents();
  295. eventProcessing = false;
  296. } else {
  297. eventQueue.add(new BeforeGraphClearEvent(sourceId, timeId));
  298. }
  299. }
  300. /**
  301. * Send a "step begins" event to all element sinks.
  302. *
  303. * @param sourceId
  304. * The graph identifier.
  305. * @param step
  306. * The step time stamp.
  307. */
  308. public void sendStepBegins(String sourceId, double step) {
  309. sendStepBegins(sourceId, sourceTime.newEvent(), step);
  310. }
  311. /**
  312. * Send a "step begins" event to all element sinks.
  313. *
  314. * @param sourceId
  315. * The graph identifier.
  316. * @param timeId
  317. * @param step
  318. */
  319. public void sendStepBegins(String sourceId, long timeId, double step) {
  320. if (!eventProcessing) {
  321. eventProcessing = true;
  322. manageEvents();
  323. for (int i = 0; i < eltsSinks.size(); i++) {
  324. eltsSinks.get(i).stepBegins(sourceId, timeId, step);
  325. }
  326. manageEvents();
  327. eventProcessing = false;
  328. } else {
  329. eventQueue.add(new StepBeginsEvent(sourceId, timeId, step));
  330. }
  331. }
  332. /**
  333. * Send a "node added" event to all element sinks.
  334. *
  335. * @param sourceId
  336. * The source identifier.
  337. * @param nodeId
  338. * The node identifier.
  339. */
  340. public void sendNodeAdded(String sourceId, String nodeId) {
  341. sendNodeAdded(sourceId, sourceTime.newEvent(), nodeId);
  342. }
  343. /**
  344. * Send a "node added" event to all element sinks.
  345. *
  346. * @param sourceId
  347. * The source identifier.
  348. * @param timeId
  349. * @param nodeId
  350. * The node identifier.
  351. */
  352. public void sendNodeAdded(String sourceId, long timeId, String nodeId) {
  353. if (!eventProcessing) {
  354. eventProcessing = true;
  355. manageEvents();
  356. for (int i = 0; i < eltsSinks.size(); i++) {
  357. eltsSinks.get(i).nodeAdded(sourceId, timeId, nodeId);
  358. }
  359. manageEvents();
  360. eventProcessing = false;
  361. } else {
  362. eventQueue.add(new AfterNodeAddEvent(sourceId, timeId, nodeId));
  363. }
  364. }
  365. /**
  366. * Send a "node removed" event to all element sinks.
  367. *
  368. * @param sourceId
  369. * The graph identifier.
  370. * @param nodeId
  371. * The node identifier.
  372. */
  373. public void sendNodeRemoved(String sourceId, String nodeId) {
  374. sendNodeRemoved(sourceId, sourceTime.newEvent(), nodeId);
  375. }
  376. /**
  377. * Send a "node removed" event to all element sinks.
  378. *
  379. * @param sourceId
  380. * The graph identifier.
  381. * @param timeId
  382. * @param nodeId
  383. * The node identifier.
  384. */
  385. public void sendNodeRemoved(String sourceId, long timeId, String nodeId) {
  386. if (!eventProcessing) {
  387. eventProcessing = true;
  388. manageEvents();
  389. for (int i = 0; i < eltsSinks.size(); i++) {
  390. eltsSinks.get(i).nodeRemoved(sourceId, timeId, nodeId);
  391. }
  392. manageEvents();
  393. eventProcessing = false;
  394. } else {
  395. eventQueue.add(new BeforeNodeRemoveEvent(sourceId, timeId, nodeId));
  396. }
  397. }
  398. /**
  399. * Send an "edge added" event to all element sinks.
  400. *
  401. * @param sourceId
  402. * The source identifier.
  403. * @param edgeId
  404. * The edge identifier.
  405. * @param fromNodeId
  406. * The edge start node.
  407. * @param toNodeId
  408. * The edge end node.
  409. * @param directed
  410. * Is the edge directed?.
  411. */
  412. public void sendEdgeAdded(String sourceId, String edgeId, String fromNodeId, String toNodeId, boolean directed) {
  413. sendEdgeAdded(sourceId, sourceTime.newEvent(), edgeId, fromNodeId, toNodeId, directed);
  414. }
  415. /**
  416. * Send an "edge added" event to all element sinks.
  417. *
  418. * @param sourceId
  419. * The source identifier.
  420. * @param timeId
  421. * @param edgeId
  422. * The edge identifier.
  423. * @param fromNodeId
  424. * The edge start node.
  425. * @param toNodeId
  426. * The edge end node.
  427. * @param directed
  428. * Is the edge directed?.
  429. */
  430. public void sendEdgeAdded(String sourceId, long timeId, String edgeId, String fromNodeId, String toNodeId,
  431. boolean directed) {
  432. if (!eventProcessing) {
  433. eventProcessing = true;
  434. manageEvents();
  435. for (int i = 0; i < eltsSinks.size(); i++) {
  436. eltsSinks.get(i).edgeAdded(sourceId, timeId, edgeId, fromNodeId, toNodeId, directed);
  437. }
  438. manageEvents();
  439. eventProcessing = false;
  440. } else {
  441. eventQueue.add(new AfterEdgeAddEvent(sourceId, timeId, edgeId, fromNodeId, toNodeId, directed));
  442. }
  443. }
  444. /**
  445. * Send a "edge removed" event to all element sinks.
  446. *
  447. * @param sourceId
  448. * The source identifier.
  449. * @param edgeId
  450. * The edge identifier.
  451. */
  452. public void sendEdgeRemoved(String sourceId, String edgeId) {
  453. sendEdgeRemoved(sourceId, sourceTime.newEvent(), edgeId);
  454. }
  455. /**
  456. * Send a "edge removed" event to all element sinks.
  457. *
  458. * @param sourceId
  459. * The source identifier.
  460. * @param timeId
  461. * @param edgeId
  462. * The edge identifier.
  463. */
  464. public void sendEdgeRemoved(String sourceId, long timeId, String edgeId) {
  465. if (!eventProcessing) {
  466. eventProcessing = true;
  467. manageEvents();
  468. for (int i = 0; i < eltsSinks.size(); i++) {
  469. eltsSinks.get(i).edgeRemoved(sourceId, timeId, edgeId);
  470. }
  471. manageEvents();
  472. eventProcessing = false;
  473. } else {
  474. eventQueue.add(new BeforeEdgeRemoveEvent(sourceId, timeId, edgeId));
  475. }
  476. }
  477. /**
  478. * Send a "edge attribute added" event to all attribute sinks.
  479. *
  480. * @param sourceId
  481. * The source identifier.
  482. * @param edgeId
  483. * The edge identifier.
  484. * @param attribute
  485. * The attribute name.
  486. * @param value
  487. * The attribute value.
  488. */
  489. public void sendEdgeAttributeAdded(String sourceId, String edgeId, String attribute, Object value) {
  490. sendAttributeChangedEvent(sourceId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.ADD, null, value);
  491. }
  492. /**
  493. * Send a "edge attribute added" event to all attribute sinks.
  494. *
  495. * @param sourceId
  496. * The source identifier.
  497. * @param timeId
  498. * @param edgeId
  499. * The edge identifier.
  500. * @param attribute
  501. * The attribute name.
  502. * @param value
  503. * The attribute value.
  504. */
  505. public void sendEdgeAttributeAdded(String sourceId, long timeId, String edgeId, String attribute, Object value) {
  506. sendAttributeChangedEvent(sourceId, timeId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.ADD, null,
  507. value);
  508. }
  509. /**
  510. * Send a "edge attribute changed" event to all attribute sinks.
  511. *
  512. * @param sourceId
  513. * The source identifier.
  514. * @param edgeId
  515. * The edge identifier.
  516. * @param attribute
  517. * The attribute name.
  518. * @param oldValue
  519. * The old attribute value.
  520. * @param newValue
  521. * The new attribute value.
  522. */
  523. public void sendEdgeAttributeChanged(String sourceId, String edgeId, String attribute, Object oldValue,
  524. Object newValue) {
  525. sendAttributeChangedEvent(sourceId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.CHANGE, oldValue,
  526. newValue);
  527. }
  528. /**
  529. * Send a "edge attribute changed" event to all attribute sinks.
  530. *
  531. * @param sourceId
  532. * The source identifier.
  533. * @param timeId
  534. * @param edgeId
  535. * The edge identifier.
  536. * @param attribute
  537. * The attribute name.
  538. * @param oldValue
  539. * The old attribute value.
  540. * @param newValue
  541. * The new attribute value.
  542. */
  543. public void sendEdgeAttributeChanged(String sourceId, long timeId, String edgeId, String attribute, Object oldValue,
  544. Object newValue) {
  545. sendAttributeChangedEvent(sourceId, timeId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.CHANGE,
  546. oldValue, newValue);
  547. }
  548. /**
  549. * Send a "edge attribute removed" event to all attribute sinks.
  550. *
  551. * @param sourceId
  552. * The source identifier.
  553. * @param edgeId
  554. * The edge identifier.
  555. * @param attribute
  556. * The attribute name.
  557. */
  558. public void sendEdgeAttributeRemoved(String sourceId, String edgeId, String attribute) {
  559. sendAttributeChangedEvent(sourceId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.REMOVE, null,
  560. null);
  561. }
  562. /**
  563. * Send a "edge attribute removed" event to all attribute sinks.
  564. *
  565. * @param sourceId
  566. * The source identifier.
  567. * @param timeId
  568. * @param edgeId
  569. * The edge identifier.
  570. * @param attribute
  571. * The attribute name.
  572. */
  573. public void sendEdgeAttributeRemoved(String sourceId, long timeId, String edgeId, String attribute) {
  574. sendAttributeChangedEvent(sourceId, timeId, edgeId, ElementType.EDGE, attribute, AttributeChangeEvent.REMOVE,
  575. null, null);
  576. }
  577. /**
  578. * Send a "graph attribute added" event to all attribute sinks.
  579. *
  580. * @param sourceId
  581. * The source identifier.
  582. * @param attribute
  583. * The attribute name.
  584. * @param value
  585. * The attribute value.
  586. */
  587. public void sendGraphAttributeAdded(String sourceId, String attribute, Object value) {
  588. sendAttributeChangedEvent(sourceId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.ADD, null, value);
  589. }
  590. /**
  591. * Send a "graph attribute added" event to all attribute sinks.
  592. *
  593. * @param sourceId
  594. * The source identifier.
  595. * @param timeId
  596. * The time identifier.
  597. * @param attribute
  598. * The attribute name.
  599. * @param value
  600. * The attribute value.
  601. */
  602. public void sendGraphAttributeAdded(String sourceId, long timeId, String attribute, Object value) {
  603. sendAttributeChangedEvent(sourceId, timeId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.ADD, null,
  604. value);
  605. }
  606. /**
  607. * Send a "graph attribute changed" event to all attribute sinks.
  608. *
  609. * @param sourceId
  610. * The source identifier.
  611. * @param attribute
  612. * The attribute name.
  613. * @param oldValue
  614. * The attribute old value.
  615. * @param newValue
  616. * The attribute new value.
  617. */
  618. public void sendGraphAttributeChanged(String sourceId, String attribute, Object oldValue, Object newValue) {
  619. sendAttributeChangedEvent(sourceId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.CHANGE, oldValue,
  620. newValue);
  621. }
  622. /**
  623. * Send a "graph attribute changed" event to all attribute sinks.
  624. *
  625. * @param sourceId
  626. * The source identifier.
  627. * @param timeId
  628. * The time identifier.
  629. * @param attribute
  630. * The attribute name.
  631. * @param oldValue
  632. * The attribute old value.
  633. * @param newValue
  634. * The attribute new value.
  635. */
  636. public void sendGraphAttributeChanged(String sourceId, long timeId, String attribute, Object oldValue,
  637. Object newValue) {
  638. sendAttributeChangedEvent(sourceId, timeId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.CHANGE,
  639. oldValue, newValue);
  640. }
  641. /**
  642. * Send a "graph attribute removed" event to all attribute sinks.
  643. *
  644. * @param sourceId
  645. * The source identifier.
  646. * @param attribute
  647. * The attribute name.
  648. */
  649. public void sendGraphAttributeRemoved(String sourceId, String attribute) {
  650. sendAttributeChangedEvent(sourceId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.REMOVE, null,
  651. null);
  652. }
  653. /**
  654. * Send a "graph attribute removed" event to all attribute sinks.
  655. *
  656. * @param sourceId
  657. * The source identifier.
  658. * @param timeId
  659. * The time identifier.
  660. * @param attribute
  661. * The attribute name.
  662. */
  663. public void sendGraphAttributeRemoved(String sourceId, long timeId, String attribute) {
  664. sendAttributeChangedEvent(sourceId, timeId, null, ElementType.GRAPH, attribute, AttributeChangeEvent.REMOVE,
  665. null, null);
  666. }
  667. /**
  668. * Send a "node attribute added" event to all attribute sinks.
  669. *
  670. * @param sourceId
  671. * The source identifier.
  672. * @param nodeId
  673. * The node identifier.
  674. * @param attribute
  675. * The attribute name.
  676. * @param value
  677. * The attribute value.
  678. */
  679. public void sendNodeAttributeAdded(String sourceId, String nodeId, String attribute, Object value) {
  680. sendAttributeChangedEvent(sourceId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.ADD, null, value);
  681. }
  682. /**
  683. * Send a "node attribute added" event to all attribute sinks.
  684. *
  685. * @param sourceId
  686. * The source identifier.
  687. * @param timeId
  688. * The time identifier.
  689. * @param nodeId
  690. * The node identifier.
  691. * @param attribute
  692. * The attribute name.
  693. * @param value
  694. * The attribute value.
  695. */
  696. public void sendNodeAttributeAdded(String sourceId, long timeId, String nodeId, String attribute, Object value) {
  697. sendAttributeChangedEvent(sourceId, timeId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.ADD, null,
  698. value);
  699. }
  700. /**
  701. * Send a "node attribute changed" event to all attribute sinks.
  702. *
  703. * @param sourceId
  704. * The source identifier.
  705. * @param nodeId
  706. * The node identifier.
  707. * @param attribute
  708. * The attribute name.
  709. * @param oldValue
  710. * The attribute old value.
  711. * @param newValue
  712. * The attribute new value.
  713. */
  714. public void sendNodeAttributeChanged(String sourceId, String nodeId, String attribute, Object oldValue,
  715. Object newValue) {
  716. sendAttributeChangedEvent(sourceId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.CHANGE, oldValue,
  717. newValue);
  718. }
  719. /**
  720. * Send a "node attribute changed" event to all attribute sinks.
  721. *
  722. * @param sourceId
  723. * The source identifier.
  724. * @param timeId
  725. * The time identifier.
  726. * @param nodeId
  727. * The node identifier.
  728. * @param attribute
  729. * The attribute name.
  730. * @param oldValue
  731. * The attribute old value.
  732. * @param newValue
  733. * The attribute new value.
  734. */
  735. public void sendNodeAttributeChanged(String sourceId, long timeId, String nodeId, String attribute, Object oldValue,
  736. Object newValue) {
  737. sendAttributeChangedEvent(sourceId, timeId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.CHANGE,
  738. oldValue, newValue);
  739. }
  740. /**
  741. * Send a "node attribute removed" event to all attribute sinks.
  742. *
  743. * @param sourceId
  744. * The source identifier.
  745. * @param nodeId
  746. * The node identifier.
  747. * @param attribute
  748. * The attribute name.
  749. */
  750. public void sendNodeAttributeRemoved(String sourceId, String nodeId, String attribute) {
  751. sendAttributeChangedEvent(sourceId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.REMOVE, null,
  752. null);
  753. }
  754. /**
  755. * Send a "node attribute removed" event to all attribute sinks.
  756. *
  757. * @param sourceId
  758. * The source identifier.
  759. * @param timeId
  760. * @param nodeId
  761. * The node identifier.
  762. * @param attribute
  763. * The attribute name.
  764. */
  765. public void sendNodeAttributeRemoved(String sourceId, long timeId, String nodeId, String attribute) {
  766. sendAttributeChangedEvent(sourceId, timeId, nodeId, ElementType.NODE, attribute, AttributeChangeEvent.REMOVE,
  767. null, null);
  768. }
  769. /**
  770. * Send a add/change/remove attribute event on an element. This method is a
  771. * generic way of notifying of an attribute change and is equivalent to
  772. * individual send*Attribute*() methods.
  773. *
  774. * @param sourceId
  775. * The source identifier.
  776. * @param eltId
  777. * The changed element identifier.
  778. * @param eltType
  779. * The changed element type.
  780. * @param attribute
  781. * The changed attribute.
  782. * @param event
  783. * The add/change/remove action.
  784. * @param oldValue
  785. * The old attribute value (null if the attribute is removed or
  786. * added).
  787. * @param newValue
  788. * The new attribute value (null if removed).
  789. */
  790. public void sendAttributeChangedEvent(String sourceId, String eltId, ElementType eltType, String attribute,
  791. AttributeChangeEvent event, Object oldValue, Object newValue) {
  792. sendAttributeChangedEvent(sourceId, sourceTime.newEvent(), eltId, eltType, attribute, event, oldValue,
  793. newValue);
  794. }
  795. /**
  796. * Send a add/change/remove attribute event on an element. This method is a
  797. * generic way of notifying of an attribute change and is equivalent to
  798. * individual send*Attribute*() methods.
  799. *
  800. * @param sourceId
  801. * The source identifier.
  802. * @param timeId
  803. * The time identifier.
  804. * @param eltId
  805. * The changed element identifier.
  806. * @param eltType
  807. * The changed element type.
  808. * @param attribute
  809. * The changed attribute.
  810. * @param event
  811. * The add/change/remove action.
  812. * @param oldValue
  813. * The old attribute value (null if the attribute is removed or
  814. * added).
  815. * @param newValue
  816. * The new attribute value (null if removed).
  817. */
  818. public void sendAttributeChangedEvent(String sourceId, long timeId, String eltId, ElementType eltType,
  819. String attribute, AttributeChangeEvent event, Object oldValue, Object newValue) {
  820. if (!eventProcessing) {
  821. eventProcessing = true;
  822. manageEvents();
  823. if (event == AttributeChangeEvent.ADD) {
  824. if (eltType == ElementType.NODE) {
  825. for (int i = 0; i < attrSinks.size(); i++) {
  826. attrSinks.get(i).nodeAttributeAdded(sourceId, timeId, eltId, attribute, newValue);
  827. }
  828. } else if (eltType == ElementType.EDGE) {
  829. for (int i = 0; i < attrSinks.size(); i++) {
  830. attrSinks.get(i).edgeAttributeAdded(sourceId, timeId, eltId, attribute, newValue);
  831. }
  832. } else {
  833. for (int i = 0; i < attrSinks.size(); i++) {
  834. attrSinks.get(i).graphAttributeAdded(sourceId, timeId, attribute, newValue);
  835. }
  836. }
  837. } else if (event == AttributeChangeEvent.REMOVE) {
  838. if (eltType == ElementType.NODE) {
  839. for (int i = 0; i < attrSinks.size(); i++) {
  840. attrSinks.get(i).nodeAttributeRemoved(sourceId, timeId, eltId, attribute);
  841. }
  842. } else if (eltType == ElementType.EDGE) {
  843. for (int i = 0; i < attrSinks.size(); i++) {
  844. attrSinks.get(i).edgeAttributeRemoved(sourceId, timeId, eltId, attribute);
  845. }
  846. } else {
  847. for (int i = 0; i < attrSinks.size(); i++) {
  848. attrSinks.get(i).graphAttributeRemoved(sourceId, timeId, attribute);
  849. }
  850. }
  851. } else {
  852. if (eltType == ElementType.NODE) {
  853. for (int i = 0; i < attrSinks.size(); i++) {
  854. attrSinks.get(i).nodeAttributeChanged(sourceId, timeId, eltId, attribute, oldValue, newValue);
  855. }
  856. } else if (eltType == ElementType.EDGE) {
  857. for (int i = 0; i < attrSinks.size(); i++) {
  858. attrSinks.get(i).edgeAttributeChanged(sourceId, timeId, eltId, attribute, oldValue, newValue);
  859. }
  860. } else {
  861. for (int i = 0; i < attrSinks.size(); i++) {
  862. attrSinks.get(i).graphAttributeChanged(sourceId, timeId, attribute, oldValue, newValue);
  863. }
  864. }
  865. }
  866. manageEvents();
  867. eventProcessing = false;
  868. } else {
  869. eventQueue.add(
  870. new AttributeChangedEvent(sourceId, timeId, eltId, eltType, attribute, event, oldValue, newValue));
  871. }
  872. }
  873. // Deferred event management
  874. /**
  875. * If in "event processing mode", ensure all pending events are processed.
  876. */
  877. protected void manageEvents() {
  878. if (eventProcessing) {
  879. while (!eventQueue.isEmpty()) {
  880. eventQueue.remove().trigger();
  881. }
  882. }
  883. }
  884. // Events Management
  885. /**
  886. * Interface that provide general purpose classification for evens involved
  887. * in graph modifications.
  888. */
  889. abstract class GraphEvent {
  890. String sourceId;
  891. long timeId;
  892. GraphEvent(String sourceId, long timeId) {
  893. this.sourceId = sourceId;
  894. this.timeId = timeId;
  895. }
  896. abstract void trigger();
  897. }
  898. class AfterEdgeAddEvent extends GraphEvent {
  899. String edgeId;
  900. String fromNodeId;
  901. String toNodeId;
  902. boolean directed;
  903. AfterEdgeAddEvent(String sourceId, long timeId, String edgeId, String fromNodeId, String toNodeId,
  904. boolean directed) {
  905. super(sourceId, timeId);
  906. this.edgeId = edgeId;
  907. this.fromNodeId = fromNodeId;
  908. this.toNodeId = toNodeId;
  909. this.directed = directed;
  910. }
  911. @Override
  912. void trigger() {
  913. for (int i = 0; i < eltsSinks.size(); i++)
  914. eltsSinks.get(i).edgeAdded(sourceId, timeId, edgeId, fromNodeId, toNodeId, directed);
  915. }
  916. }
  917. class BeforeEdgeRemoveEvent extends GraphEvent {
  918. String edgeId;
  919. BeforeEdgeRemoveEvent(String sourceId, long timeId, String edgeId) {
  920. super(sourceId, timeId);
  921. this.edgeId = edgeId;
  922. }
  923. @Override
  924. void trigger() {
  925. for (int i = 0; i < eltsSinks.size(); i++)
  926. eltsSinks.get(i).edgeRemoved(sourceId, timeId, edgeId);
  927. }
  928. }
  929. class AfterNodeAddEvent extends GraphEvent {
  930. String nodeId;
  931. AfterNodeAddEvent(String sourceId, long timeId, String nodeId) {
  932. super(sourceId, timeId);
  933. this.nodeId = nodeId;
  934. }
  935. @Override
  936. void trigger() {
  937. for (int i = 0; i < eltsSinks.size(); i++)
  938. eltsSinks.get(i).nodeAdded(sourceId, timeId, nodeId);
  939. }
  940. }
  941. class BeforeNodeRemoveEvent extends GraphEvent {
  942. String nodeId;
  943. BeforeNodeRemoveEvent(String sourceId, long timeId, String nodeId) {
  944. super(sourceId, timeId);
  945. this.nodeId = nodeId;
  946. }
  947. @Override
  948. void trigger() {
  949. for (int i = 0; i < eltsSinks.size(); i++)
  950. eltsSinks.get(i).nodeRemoved(sourceId, timeId, nodeId);
  951. }
  952. }
  953. class BeforeGraphClearEvent extends GraphEvent {
  954. BeforeGraphClearEvent(String sourceId, long timeId) {
  955. super(sourceId, timeId);
  956. }
  957. @Override
  958. void trigger() {
  959. for (int i = 0; i < eltsSinks.size(); i++)
  960. eltsSinks.get(i).graphCleared(sourceId, timeId);
  961. }
  962. }
  963. class StepBeginsEvent extends GraphEvent {
  964. double step;
  965. StepBeginsEvent(String sourceId, long timeId, double step) {
  966. super(sourceId, timeId);
  967. this.step = step;
  968. }
  969. @Override
  970. void trigger() {
  971. for (int i = 0; i < eltsSinks.size(); i++)
  972. eltsSinks.get(i).stepBegins(sourceId, timeId, step);
  973. }
  974. }
  975. class AttributeChangedEvent extends GraphEvent {
  976. ElementType eltType;
  977. String eltId;
  978. String attribute;
  979. AttributeChangeEvent event;
  980. Object oldValue;
  981. Object newValue;
  982. AttributeChangedEvent(String sourceId, long timeId, String eltId, ElementType eltType, String attribute,
  983. AttributeChangeEvent event, Object oldValue, Object newValue) {
  984. super(sourceId, timeId);
  985. this.eltType = eltType;
  986. this.eltId = eltId;
  987. this.attribute = attribute;
  988. this.event = event;
  989. this.oldValue = oldValue;
  990. this.newValue = newValue;
  991. }
  992. @Override
  993. void trigger() {
  994. switch (event) {
  995. case ADD:
  996. switch (eltType) {
  997. case NODE:
  998. for (int i = 0; i < attrSinks.size(); i++)
  999. attrSinks.get(i).nodeAttributeAdded(sourceId, timeId, eltId, attribute, newValue);
  1000. break;
  1001. case EDGE:
  1002. for (int i = 0; i < attrSinks.size(); i++)
  1003. attrSinks.get(i).edgeAttributeAdded(sourceId, timeId, eltId, attribute, newValue);
  1004. break;
  1005. default:
  1006. for (int i = 0; i < attrSinks.size(); i++)
  1007. attrSinks.get(i).graphAttributeAdded(sourceId, timeId, attribute, newValue);
  1008. }
  1009. break;
  1010. case REMOVE:
  1011. switch (eltType) {
  1012. case NODE:
  1013. for (int i = 0; i < attrSinks.size(); i++)
  1014. attrSinks.get(i).nodeAttributeRemoved(sourceId, timeId, eltId, attribute);
  1015. break;
  1016. case EDGE:
  1017. for (int i = 0; i < attrSinks.size(); i++)
  1018. attrSinks.get(i).edgeAttributeRemoved(sourceId, timeId, eltId, attribute);
  1019. break;
  1020. default:
  1021. for (int i = 0; i < attrSinks.size(); i++)
  1022. attrSinks.get(i).graphAttributeRemoved(sourceId, timeId, attribute);
  1023. }
  1024. break;
  1025. default:
  1026. switch (eltType) {
  1027. case NODE:
  1028. for (int i = 0; i < attrSinks.size(); i++)
  1029. attrSinks.get(i).nodeAttributeChanged(sourceId, timeId, eltId, attribute, oldValue, newValue);
  1030. break;
  1031. case EDGE:
  1032. for (int i = 0; i < attrSinks.size(); i++)
  1033. attrSinks.get(i).edgeAttributeChanged(sourceId, timeId, eltId, attribute, oldValue, newValue);
  1034. break;
  1035. default:
  1036. for (int i = 0; i < attrSinks.size(); i++)
  1037. attrSinks.get(i).graphAttributeChanged(sourceId, timeId, attribute, oldValue, newValue);
  1038. }
  1039. }
  1040. }
  1041. }
  1042. class AddToListEvent<T> extends GraphEvent {
  1043. List<T> l;
  1044. T obj;
  1045. AddToListEvent(List<T> l, T obj) {
  1046. super(null, -1);
  1047. this.l = l;
  1048. this.obj = obj;
  1049. }
  1050. @Override
  1051. void trigger() {
  1052. l.add(obj);
  1053. }
  1054. }
  1055. class RemoveFromListEvent<T> extends GraphEvent {
  1056. List<T> l;
  1057. T obj;
  1058. RemoveFromListEvent(List<T> l, T obj) {
  1059. super(null, -1);
  1060. this.l = l;
  1061. this.obj = obj;
  1062. }
  1063. @Override
  1064. void trigger() {
  1065. l.remove(obj);
  1066. }
  1067. }
  1068. class ClearListEvent<T> extends GraphEvent {
  1069. List<T> l;
  1070. ClearListEvent(List<T> l) {
  1071. super(null, -1);
  1072. this.l = l;
  1073. }
  1074. @Override
  1075. void trigger() {
  1076. l.clear();
  1077. }
  1078. }
  1079. /**
  1080. * how many inner graphs were generated for the current graph
  1081. */
  1082. private int subGraphCounter = 1;
  1083. /**
  1084. * adds a new sub graph, it will be populated until InnerGraphFInished is
  1085. * called
  1086. */
  1087. protected void newSubGraph() {
  1088. if (subGraphCounter > 1) {
  1089. removeSink(originalSink);
  1090. multiGraph = true;
  1091. }
  1092. MyGraph g = new MyGraph(superID + "sub" + subGraphCounter);
  1093. subGraphCounter++;
  1094. addSubGraphSink(g);
  1095. usedSubGraphs.push(g);
  1096. }
  1097. /**
  1098. * adds the sub Graph to the List of subGraphs and removes it from the
  1099. * sinkLists
  1100. */
  1101. protected void subGraphFinished() {
  1102. MyGraph g = usedSubGraphs.pop();
  1103. removeSink(g);
  1104. subGraphs.add(g);
  1105. }
  1106. /**
  1107. * this returns all finished subgraphs, but does not reset the internal
  1108. * dataStructures. This can be called until a new Graph is added using
  1109. * addSink().
  1110. *
  1111. * @return all subGraphs
  1112. */
  1113. public LinkedList<MyGraph> getSubGraphs() {
  1114. return subGraphs;
  1115. }
  1116. /**
  1117. * resets the internal datastructures used for the subgraphs. This is
  1118. * automatically called with addGraph().
  1119. */
  1120. protected void resetSubGraphs() {
  1121. usedSubGraphs.removeAllElements();
  1122. subGraphCounter = 1;
  1123. subGraphs.clear();
  1124. }
  1125. }