1 package org.openprovenance.model;
2 import java.util.Collection;
3 import java.util.Arrays;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.HashMap;
7
8
9 /*** This class provides a set of indexes over information contained in
10 * an OPMGraph, facilitating its navigation. Its constructor takes an
11 * OPMGraph builds an index for it. Of course, for the index to be
12 * maintained, one cannot access, say the list of edges, and mutate
13 * it. Instead, one has to use the add methods provided.
14 *<p>
15 * Note that code is not thread-safe.
16
17 TODO: index annotation, index edges
18
19 */
20
21 public class IndexedOPMGraph extends OPMGraph {
22
23 OPMUtilities u=new OPMUtilities();
24 final OPMFactory oFactory;
25
26 private HashMap<String,Account> accountMap=new HashMap();
27 private HashMap<String,Artifact> artifactMap=new HashMap();
28 private HashMap<String,Process> processMap=new HashMap();
29 private HashMap<String,Agent> agentMap=new HashMap();
30
31
32
33 private HashMap<String,Collection<Used>> processUsedMap=new HashMap();
34
35
36
37 private HashMap<String,Collection<Used>> artifactUsedMap=new HashMap();
38 private Collection<Used> allUsed=new LinkedList();
39
40
41
42 private HashMap<String,Collection<WasGeneratedBy>> processWasGeneratedByMap=new HashMap();
43
44
45
46 private HashMap<String,Collection<WasGeneratedBy>> artifactWasGeneratedByMap=new HashMap();
47 private Collection<WasGeneratedBy> allWasGeneratedBy=new LinkedList();
48
49
50 private HashMap<String,Collection<WasDerivedFrom>> artifactCauseWasDerivedFromMap=new HashMap();
51
52
53
54 private HashMap<String,Collection<WasDerivedFrom>> artifactEffectWasDerivedFromMap=new HashMap();
55 private Collection<WasDerivedFrom> allWasDerivedFrom=new LinkedList();
56
57
58
59 private HashMap<String,Collection<WasControlledBy>> processWasControlledByMap=new HashMap();
60
61
62
63 private HashMap<String,Collection<WasControlledBy>> agentWasControlledByMap=new HashMap();
64 private Collection<WasControlledBy> allWasControlledBy=new LinkedList();
65
66
67 private HashMap<String,Collection<WasTriggeredBy>> processCauseWasTriggeredByMap=new HashMap();
68
69
70
71 private HashMap<String,Collection<WasTriggeredBy>> processEffectWasTriggeredByMap=new HashMap();
72 private Collection<WasTriggeredBy> allWasTriggeredBy=new LinkedList();
73
74
75 /*** Return all used edges for this graph. */
76 public Collection<Used> getUsed() {
77 return allUsed;
78 }
79 /*** Return all used edges with process p as an effect. */
80 public Collection<Used> getUsed(Process p) {
81 return processUsedMap.get(p.getId());
82 }
83
84 /*** Return all used edges with artifact a as a cause. */
85 public Collection<Used> getUsed(Artifact p) {
86 return artifactUsedMap.get(p.getId());
87 }
88
89 /*** Return all WasGeneratedBy edges for this graph. */
90 public Collection<WasGeneratedBy> getWasGeneratedBy() {
91 return allWasGeneratedBy;
92 }
93 /*** Return all WasGeneratedBy edges with process p as an effect. */
94 public Collection<WasGeneratedBy> getWasGeneratedBy(Process p) {
95 return processWasGeneratedByMap.get(p.getId());
96 }
97
98 /*** Return all WasGeneratedBy edges with artifact a as a cause. */
99 public Collection<WasGeneratedBy> getWasGeneratedBy(Artifact p) {
100 return artifactWasGeneratedByMap.get(p.getId());
101 }
102
103 /*** Return all WasDerivedFrom edges for this graph. */
104 public Collection<WasDerivedFrom> getWasDerivedFrom() {
105 return allWasDerivedFrom;
106 }
107 /*** Return all WasDerivedFrom edges with artifact a as a cause. */
108 public Collection<WasDerivedFrom> getWasDerivedFromWithCause(Artifact a) {
109 return artifactCauseWasDerivedFromMap.get(a.getId());
110 }
111
112 /*** Return all WasDerivedFrom edges with artifact a as an effect . */
113 public Collection<WasDerivedFrom> getWasDerivedFromWithEffect(Artifact a) {
114 return artifactEffectWasDerivedFromMap.get(a.getId());
115 }
116
117
118 /*** Return all WasTriggeredBy edges for this graph. */
119 public Collection<WasTriggeredBy> getWasTriggeredBy() {
120 return allWasTriggeredBy;
121 }
122 /*** Return all WasTriggeredBy edges with process p as a cause. */
123 public Collection<WasTriggeredBy> getWasTriggeredByWithCause(Process a) {
124 return processCauseWasTriggeredByMap.get(a.getId());
125 }
126
127 /*** Return all WasTriggeredBy edges with process a as an effect. */
128 public Collection<WasTriggeredBy> getWasTriggeredByWithEffect(Process a) {
129 return processEffectWasTriggeredByMap.get(a.getId());
130 }
131
132 /*** Return all WasControlledBy edges for this graph. */
133 public Collection<WasControlledBy> getWasControlledBy() {
134 return allWasControlledBy;
135 }
136 /*** Return all WasControlledBy edges with process p as an effect. */
137 public Collection<WasControlledBy> getWasControlledBy(Process p) {
138 return processWasControlledByMap.get(p.getId());
139 }
140
141 /*** Return all WasControlledBy edges with artifact a as a cause. */
142 public Collection<WasControlledBy> getWasControlledBy(Agent a) {
143 return agentWasControlledByMap.get(a.getId());
144
145 }
146
147
148 final protected ObjectFactory of;
149
150 public Account getAccount(String name) {
151 return accountMap.get(name);
152 }
153
154 public Account addAccount(String name, Account account) {
155 Account existing=accountMap.get(name);
156 if (existing!=null) {
157 return existing;
158 } else {
159 accountMap.put(name,account);
160 Accounts accounts=getAccounts();
161 if (accounts==null) {
162 accounts=of.createAccounts();
163 setAccounts(accounts);
164 }
165 accounts.getAccount().add(account);
166 return account;
167 }
168 }
169 public Account addAccount(Account account) {
170 return addAccount(account.getId(),account);
171 }
172
173 public Artifact addArtifact(Artifact artifact) {
174 return addArtifact(artifact.getId(),artifact);
175 }
176 public Artifact addArtifact(String name, Artifact artifact) {
177 Artifact existing=artifactMap.get(name);
178 if (existing!=null) {
179 return existing;
180 } else {
181 artifactMap.put(name,artifact);
182 Artifacts artifacts=getArtifacts();
183 if (artifacts==null) {
184 artifacts=of.createArtifacts();
185 setArtifacts(artifacts);
186 }
187 artifacts.getArtifact().add(artifact);
188 return artifact;
189 }
190 }
191
192
193
194 public Agent addAgent(Agent agent) {
195 return addAgent(agent.getId(),agent);
196 }
197 public Agent addAgent(String name, Agent agent) {
198 Agent existing=agentMap.get(name);
199 if (existing!=null) {
200 return existing;
201 } else {
202 agentMap.put(name,agent);
203 Agents agents=getAgents();
204 if (agents==null) {
205 agents=of.createAgents();
206 setAgents(agents);
207 }
208 agents.getAgent().add(agent);
209 return agent;
210 }
211 }
212
213 public Process addProcess(Process process) {
214 return addProcess(process.getId(),process);
215 }
216
217 public Process addProcess(String name, Process process) {
218 Process existing=processMap.get(name);
219 if (existing!=null) {
220 return existing;
221 } else {
222 processMap.put(name,process);
223 Processes processes=getProcesses();
224 if (processes==null) {
225 processes=of.createProcesses();
226 setProcesses(processes);
227 }
228 processes.getProcess().add(process);
229 return process;
230 }
231 }
232
233 public Process getProcess(String name) {
234 return processMap.get(name);
235 }
236 public Artifact getArtifact(String name) {
237 return artifactMap.get(name);
238 }
239 public Agent getAgent(String name) {
240 return agentMap.get(name);
241 }
242
243
244 public IndexedOPMGraph(OPMFactory oFactory, OPMGraph graph) {
245 this.oFactory=oFactory;
246 this.of=oFactory.getObjectFactory();
247 if (graph.getAccounts()!=null) {
248 for (Account acc: graph.getAccounts().getAccount()) {
249 addAccount(acc);
250 }
251 }
252
253 if (graph.getArtifacts()!=null) {
254 for (Artifact acc: graph.getArtifacts().getArtifact()) {
255 addArtifact(acc);
256 }
257 }
258
259 if (graph.getAgents()!=null) {
260 for (Agent acc: graph.getAgents().getAgent()) {
261 addAgent(acc);
262 }
263 }
264
265 if (graph.getProcesses()!=null) {
266 for (Process acc: graph.getProcesses().getProcess()) {
267 addProcess(acc);
268 }
269 }
270
271 if (graph.getCausalDependencies()!=null) {
272 if (getCausalDependencies()==null) {
273 setCausalDependencies(of.createCausalDependencies());
274 }
275 List<Edge> edges=u.getEdges(graph);
276
277 for (Edge edge: edges) {
278 if (edge instanceof Used) {
279
280 addUsed(oFactory.newUsed((Used) edge));
281 }
282 if (edge instanceof WasGeneratedBy) {
283
284 addWasGeneratedBy(oFactory.newWasGeneratedBy((WasGeneratedBy) edge));
285 }
286 if (edge instanceof WasDerivedFrom) {
287
288 addWasDerivedFrom(oFactory.newWasDerivedFrom((WasDerivedFrom) edge));
289 }
290 if (edge instanceof WasControlledBy) {
291
292 addWasControlledBy(oFactory.newWasControlledBy((WasControlledBy) edge));
293 }
294 if (edge instanceof WasTriggeredBy) {
295
296 addWasTriggeredBy(oFactory.newWasTriggeredBy((WasTriggeredBy) edge));
297 }
298 }
299 }
300 }
301
302 /*** Only adds to acc1s elements of acc2s that are not already in acc1s. */
303 void addNewAccounts(Collection<AccountRef> acc1s, Collection<AccountRef> acc2s) {
304 for (AccountRef acc2: acc2s) {
305 if (!(acc1s.contains(acc2))) {
306 acc1s.add(acc2);
307 }
308 }
309 }
310
311 /*** Add a used edge to the graph. Update processUsedMap and
312 artifactUsedMap accordingly. By doing so, aggregate all used
313 edges (p,r,a) with different accounts in a single edge.
314 Return the used edge itself (if it had not been encountered
315 before), or the instance encountered before.*/
316
317 public Used addUsed(Used used) {
318 ProcessRef pid=used.getEffect();
319 Process p=(Process)(pid.getRef());
320 ArtifactRef aid=used.getCause();
321 Artifact a=(Artifact)(aid.getRef());
322 Role r=used.getRole();
323 Collection<AccountRef> accs=used.getAccount();
324
325 Used result=used;
326
327 boolean found=false;
328 Collection<Used> ucoll=processUsedMap.get(p.getId());
329 if (ucoll==null) {
330 ucoll=new LinkedList();
331 ucoll.add(used);
332 processUsedMap.put(p.getId(),ucoll);
333 } else {
334
335 for (Used u: ucoll) {
336
337 if (aid.equals(u.getCause())
338 &&
339 r.equals(u.getRole())) {
340 addNewAccounts(u.getAccount(),accs);
341 result=u;
342 found=true;
343 }
344 }
345 if (!found) {
346 ucoll.add(used);
347 }
348 }
349
350 ucoll=artifactUsedMap.get(a.getId());
351 if (ucoll==null) {
352 ucoll=new LinkedList();
353 ucoll.add(used);
354 artifactUsedMap.put(a.getId(),ucoll);
355 } else {
356 if (!found) {
357
358
359 ucoll.add(used);
360 }
361 }
362
363 if (!found) {
364 allUsed.add(used);
365 getCausalDependencies().getUsedOrWasGeneratedByOrWasTriggeredBy().add(used);
366 }
367 return result;
368 }
369
370
371
372
373 /*** Add a wasGeneratedBy edge to the graph. Update processWasGeneratedByMap and
374 artifactWasGeneratedByMap accordingly. By doing so, aggregate all wasGeneratedBy
375 edges (a,r,p) with different accounts in a single edge.
376 Return the wasGeneratedBy edge itself (if it had not been encountered
377 before), or the instance encountered before.*/
378
379 public WasGeneratedBy addWasGeneratedBy(WasGeneratedBy wasGeneratedBy) {
380 ProcessRef pid=wasGeneratedBy.getCause();
381 Process p=(Process)(pid.getRef());
382 ArtifactRef aid=wasGeneratedBy.getEffect();
383 Artifact a=(Artifact)(aid.getRef());
384 Role r=wasGeneratedBy.getRole();
385 Collection<AccountRef> accs=wasGeneratedBy.getAccount();
386
387 WasGeneratedBy result=wasGeneratedBy;
388
389 boolean found=false;
390 Collection<WasGeneratedBy> gcoll=processWasGeneratedByMap.get(p.getId());
391 if (gcoll==null) {
392 gcoll=new LinkedList();
393 gcoll.add(wasGeneratedBy);
394 processWasGeneratedByMap.put(p.getId(),gcoll);
395 } else {
396
397 for (WasGeneratedBy u: gcoll) {
398
399 if (aid.equals(u.getEffect())
400 &&
401 r.equals(u.getRole())) {
402 addNewAccounts(u.getAccount(),accs);
403 result=u;
404 found=true;
405 }
406 }
407 if (!found) {
408 gcoll.add(wasGeneratedBy);
409 }
410 }
411
412 gcoll=artifactWasGeneratedByMap.get(a.getId());
413 if (gcoll==null) {
414 gcoll=new LinkedList();
415 gcoll.add(wasGeneratedBy);
416 artifactWasGeneratedByMap.put(a.getId(),gcoll);
417 } else {
418 if (!found) {
419
420
421 gcoll.add(wasGeneratedBy);
422 }
423 }
424
425 if (!found) {
426 allWasGeneratedBy.add(wasGeneratedBy);
427 getCausalDependencies().getUsedOrWasGeneratedByOrWasTriggeredBy().add(wasGeneratedBy);
428 }
429 return result;
430 }
431
432
433 /*** Add a wasDerivedFrom edge to the graph. Update processWasDerivedFromMap and
434 artifactWasDerivedFromMap accordingly. By doing so, aggregate all wasDerivedFrom
435 edges (a1,r,a2) with different accounts in a single edge.
436 Return the wasDerivedFrom edge itself (if it had not been encountered
437 before), or the instance encountered before.*/
438
439 public WasDerivedFrom addWasDerivedFrom(WasDerivedFrom wasDerivedFrom) {
440 ArtifactRef aid2=wasDerivedFrom.getEffect();
441 Artifact a2=(Artifact)(aid2.getRef());
442 ArtifactRef aid1=wasDerivedFrom.getCause();
443 Artifact a1=(Artifact)(aid1.getRef());
444 Collection<AccountRef> accs=wasDerivedFrom.getAccount();
445
446 WasDerivedFrom result=wasDerivedFrom;
447
448 boolean found=false;
449 Collection<WasDerivedFrom> dcoll=artifactCauseWasDerivedFromMap.get(a1.getId());
450 if (dcoll==null) {
451 dcoll=new LinkedList();
452 dcoll.add(wasDerivedFrom);
453 artifactCauseWasDerivedFromMap.put(a1.getId(),dcoll);
454 } else {
455
456 for (WasDerivedFrom d: dcoll) {
457
458 if ((aid1.equals(d.getCause())) && (aid2.equals(d.getEffect()))) {
459 addNewAccounts(d.getAccount(),accs);
460 result=d;
461 found=true;
462 }
463 }
464 if (!found) {
465 dcoll.add(wasDerivedFrom);
466 }
467 }
468
469 dcoll=artifactEffectWasDerivedFromMap.get(a2.getId());
470 if (dcoll==null) {
471 dcoll=new LinkedList();
472 dcoll.add(wasDerivedFrom);
473 artifactEffectWasDerivedFromMap.put(a2.getId(),dcoll);
474 } else {
475 if (!found) {
476
477
478 dcoll.add(wasDerivedFrom);
479 }
480 }
481
482 if (!found) {
483 allWasDerivedFrom.add(wasDerivedFrom);
484 getCausalDependencies().getUsedOrWasGeneratedByOrWasTriggeredBy().add(wasDerivedFrom);
485 }
486
487 return result;
488 }
489
490
491 /*** Add a wasControlledBy edge to the graph. Update processWasControlledByMap and
492 agentWasControlledByMap accordingly. By doing so, aggregate all wasControlledBy
493 edges (p,r,a) with different accounts in a single edge.
494 Return the wasControlledBy edge itself (if it had not been encountered
495 before), or the instance encountered before.*/
496
497 public WasControlledBy addWasControlledBy(WasControlledBy wasControlledBy) {
498 ProcessRef pid=wasControlledBy.getEffect();
499 Process p=(Process)(pid.getRef());
500 AgentRef aid=wasControlledBy.getCause();
501 Agent a=(Agent)(aid.getRef());
502 Role r=wasControlledBy.getRole();
503 Collection<AccountRef> accs=wasControlledBy.getAccount();
504
505 WasControlledBy result=wasControlledBy;
506
507 boolean found=false;
508 Collection<WasControlledBy> ccoll=processWasControlledByMap.get(p.getId());
509 if (ccoll==null) {
510 ccoll=new LinkedList();
511 ccoll.add(wasControlledBy);
512 processWasControlledByMap.put(p.getId(),ccoll);
513 } else {
514
515 for (WasControlledBy u: ccoll) {
516
517 if (aid.equals(u.getCause())
518 &&
519 r.equals(u.getRole())) {
520 addNewAccounts(u.getAccount(),accs);
521 result=u;
522 found=true;
523 }
524 }
525 if (!found) {
526 ccoll.add(wasControlledBy);
527 }
528 }
529
530 ccoll=agentWasControlledByMap.get(a.getId());
531 if (ccoll==null) {
532 ccoll=new LinkedList();
533 ccoll.add(wasControlledBy);
534 agentWasControlledByMap.put(p.getId(),ccoll);
535 } else {
536 if (!found) {
537
538
539 ccoll.add(wasControlledBy);
540 }
541 }
542
543 if (!found) {
544 allWasControlledBy.add(wasControlledBy);
545 getCausalDependencies().getUsedOrWasGeneratedByOrWasTriggeredBy().add(wasControlledBy);
546 }
547 return result;
548 }
549
550 /*** Add a wasTriggeredBy edge to the graph. Update processWasTriggeredByMap and
551 artifactWasTriggeredByMap accordingly. By doing so, aggregate all wasTriggeredBy
552 edges (p1,r,p2) with different accounts in a single edge.
553 Return the wasTriggeredBy edge itself (if it had not been encountered
554 before), or the instance encountered before.*/
555
556 public WasTriggeredBy addWasTriggeredBy(WasTriggeredBy wasTriggeredBy) {
557 ProcessRef pid2=wasTriggeredBy.getEffect();
558 Process p2=(Process)(pid2.getRef());
559 ProcessRef pid1=wasTriggeredBy.getCause();
560 Process p1=(Process)(pid1.getRef());
561 Collection<AccountRef> accs=wasTriggeredBy.getAccount();
562
563 WasTriggeredBy result=wasTriggeredBy;
564
565 boolean found=false;
566 Collection<WasTriggeredBy> dcoll=processCauseWasTriggeredByMap.get(p1.getId());
567 if (dcoll==null) {
568 dcoll=new LinkedList();
569 dcoll.add(wasTriggeredBy);
570 processCauseWasTriggeredByMap.put(p1.getId(),dcoll);
571 } else {
572
573 for (WasTriggeredBy d: dcoll) {
574
575 if ( (pid1.equals(d.getCause())) && (pid2.equals(d.getEffect()))) {
576 addNewAccounts(d.getAccount(),accs);
577 result=d;
578 found=true;
579 }
580 }
581 if (!found) {
582 dcoll.add(wasTriggeredBy);
583 }
584 }
585
586 dcoll=processEffectWasTriggeredByMap.get(p2.getId());
587 if (dcoll==null) {
588 dcoll=new LinkedList();
589 dcoll.add(wasTriggeredBy);
590 processEffectWasTriggeredByMap.put(p2.getId(),dcoll);
591 } else {
592 if (!found) {
593
594
595 dcoll.add(wasTriggeredBy);
596 }
597 }
598
599 if (!found) {
600 allWasTriggeredBy.add(wasTriggeredBy);
601 getCausalDependencies().getUsedOrWasGeneratedByOrWasTriggeredBy().add(wasTriggeredBy);
602 }
603 return result;
604 }
605
606 }