MySourceBase.java 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  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. Debug.out(originalSink.toString());
  1090. removeSink(originalSink);
  1091. multiGraph = true;
  1092. }
  1093. MyGraph g = new MyGraph(superID + "sub" + subGraphCounter);
  1094. subGraphCounter++;
  1095. addSubGraphSink(g);
  1096. usedSubGraphs.push(g);
  1097. }
  1098. /**
  1099. * adds the sub Graph to the List of subGraphs and removes it from the
  1100. * sinkLists
  1101. */
  1102. protected void subGraphFinished() {
  1103. MyGraph g = usedSubGraphs.pop();
  1104. removeSink(g);
  1105. subGraphs.add(g);
  1106. }
  1107. /**
  1108. * this returns all finished subgraphs, but does not reset the internal
  1109. * dataStructures. This can be called until a new Graph is added using
  1110. * addSink().
  1111. *
  1112. * @return all subGraphs
  1113. */
  1114. public LinkedList<MyGraph> getSubGraphs() {
  1115. return subGraphs;
  1116. }
  1117. /**
  1118. * resets the internal datastructures used for the subgraphs. This is
  1119. * automatically called with addGraph().
  1120. */
  1121. protected void resetSubGraphs() {
  1122. usedSubGraphs.removeAllElements();
  1123. subGraphCounter = 1;
  1124. subGraphs.clear();
  1125. }
  1126. }