View Javadoc

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      /* Collection of Used edges that have a given process as an
32       * effect. */
33      private HashMap<String,Collection<Used>> processUsedMap=new HashMap();
34  
35      /* Collection of Used edges that have a given artifact as a
36       * cause. */
37      private HashMap<String,Collection<Used>> artifactUsedMap=new HashMap();
38      private Collection<Used> allUsed=new LinkedList();
39  
40      /* Collection of WasGeneratedBy edges that have a given process as a
41       * cause. */
42      private HashMap<String,Collection<WasGeneratedBy>> processWasGeneratedByMap=new HashMap();
43  
44      /* Collection of WasGeneratedBy edges that have a given artifact as an
45       * effect. */
46      private HashMap<String,Collection<WasGeneratedBy>> artifactWasGeneratedByMap=new HashMap();
47      private Collection<WasGeneratedBy> allWasGeneratedBy=new LinkedList();
48  
49      /* Collection of WasDerivedFrom edges that have a given artifact as a cause. */
50      private HashMap<String,Collection<WasDerivedFrom>> artifactCauseWasDerivedFromMap=new HashMap();
51  
52      /* Collection of WasDerivedFrom edges that have a given artifact as an
53       * effect. */
54      private HashMap<String,Collection<WasDerivedFrom>> artifactEffectWasDerivedFromMap=new HashMap();
55      private Collection<WasDerivedFrom> allWasDerivedFrom=new LinkedList();
56  
57      /* Collection of WasControlledBy edges that have a given process as an
58       * effect. */
59      private HashMap<String,Collection<WasControlledBy>> processWasControlledByMap=new HashMap();
60  
61      /* Collection of WasControlledBy edges that have a given agent as a
62       * cause. */
63      private HashMap<String,Collection<WasControlledBy>> agentWasControlledByMap=new HashMap();
64      private Collection<WasControlledBy> allWasControlledBy=new LinkedList();
65  
66      /* Collection of WasTriggeredBy edges that have a given process as a cause. */
67      private HashMap<String,Collection<WasTriggeredBy>> processCauseWasTriggeredByMap=new HashMap();
68  
69      /* Collection of WasTriggeredBy edges that have a given process as an
70       * effect. */
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                     /* clone to ensure that original graph is not mutated. */
280                     addUsed(oFactory.newUsed((Used) edge));  
281                 }
282                 if (edge instanceof WasGeneratedBy) {
283                     /* clone to ensure that original graph is not mutated. */
284                     addWasGeneratedBy(oFactory.newWasGeneratedBy((WasGeneratedBy) edge));  
285                 }
286                 if (edge instanceof WasDerivedFrom) {
287                     /* clone to ensure that original graph is not mutated. */
288                     addWasDerivedFrom(oFactory.newWasDerivedFrom((WasDerivedFrom) edge));  
289                 }
290                 if (edge instanceof WasControlledBy) {
291                     /* clone to ensure that original graph is not mutated. */
292                     addWasControlledBy(oFactory.newWasControlledBy((WasControlledBy) edge));  
293                 }
294                 if (edge instanceof WasTriggeredBy) {
295                     /* clone to ensure that original graph is not mutated. */
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                 // if we had not found it in the first table, then we
358                 // have to add it here too
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                 // if we had not found it in the first table, then we
420                 // have to add it here too
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                 // if we had not found it in the first table, then we
477                 // have to add it here too
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                 // if we had not found it in the first table, then we
538                 // have to add it here too
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                 // if we had not found it in the first table, then we
594                 // have to add it here too
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 }