]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.diagram/src/org/simantics/interop/diagram/Diagram.java
15174e65378d43565cd7692dda0a58adba966486
[simantics/interop.git] / org.simantics.interop.diagram / src / org / simantics / interop / diagram / Diagram.java
1 package org.simantics.interop.diagram;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10 import java.util.Stack;
11
12 import org.simantics.databoard.Bindings;
13 import org.simantics.db.ReadGraph;
14 import org.simantics.db.RequestProcessor;
15 import org.simantics.db.Resource;
16 import org.simantics.db.WriteGraph;
17 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
18 import org.simantics.db.common.request.ResourceRead;
19 import org.simantics.db.common.utils.OrderedSetUtils;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
22 import org.simantics.db.exception.NoSingleResultException;
23 import org.simantics.db.exception.ServiceException;
24 import org.simantics.db.layer0.adapter.Template;
25 import org.simantics.diagram.stubs.DiagramResource;
26 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
27 import org.simantics.g2d.page.DiagramDesc;
28 import org.simantics.layer0.Layer0;
29 import org.simantics.modeling.ModelingResources;
30 import org.simantics.operation.Layer0X;
31 import org.simantics.simulation.ontology.SimulationResource;
32 import org.simantics.structural.stubs.StructuralResource2;
33 import org.simantics.utils.datastructures.Arrays;
34 import org.simantics.utils.page.PageDesc;
35
36
37 /**
38  * @author Marko Luukkainen
39  */
40 public abstract class Diagram<T extends Symbol> {
41         
42         public static boolean DO_NO_MIX_SECTION_NAMES = false;
43         public static boolean USE_MERGE_CONNECTS = true;
44         
45         private Resource composite;
46         private Resource diagram;
47                 
48         private Map<Resource,Integer> indexMap  = new HashMap<Resource, Integer>();
49         
50         private Map<Resource,T> elementToSymbolMap = new HashMap<Resource, T>();
51         
52         private Map<Resource,Diagram<T>> compositeToDiagramMap = new HashMap<Resource, Diagram<T>>();
53         
54         protected Diagram(ReadGraph g, Resource composite, Resource diagram) throws DatabaseException {
55                 this.composite = composite;
56                 this.diagram = diagram;
57         }
58         
59         protected abstract Diagram<T> construct(ReadGraph g, Resource composite, Resource diagram) throws DatabaseException;
60         protected abstract T constructSymbol(ReadGraph g, Resource element, Resource component) throws DatabaseException;
61         
62         public Resource getComposite() {
63                 return composite;
64         }
65         
66         public Resource getDiagram() {
67                 return diagram;
68         }
69         
70         
71         public void clearCaches() {
72                 for (Diagram<T> d : compositeToDiagramMap.values()) {
73                         for (T s : d.elementToSymbolMap.values())
74                                 s.dispose();
75                         d.elementToSymbolMap.clear();
76                 }
77                 compositeToDiagramMap.clear();
78         }
79         
80         
81         public String generateName(ReadGraph g, Resource type, String name) throws DatabaseException {
82                 Layer0 l0 = Layer0.getInstance(g);
83                 Layer0X l0x = Layer0X.getInstance(g);
84                 String prefix = g.getPossibleRelatedValue(type, l0x.HasGeneratedNamePrefix);
85                 if (prefix == null || prefix.length() == 0)
86                         prefix = g.getRelatedValue(type, l0.HasName);
87                 prefix += "_";          
88                 Set<String> reserved = null;
89                 if (name != null) {
90                         reserved = getAllModuleNamesForModel(g, composite);
91                         int index = 0;
92                         String realname = name + "_" + prefix;
93                         while (true) {
94                                 String toTry = realname + Integer.toString(index);
95                                 if (!reserved.contains(toTry))
96                                         break;
97                                 index++;
98                         }
99                         realname += Integer.toString(index);
100                         return realname;
101                 }
102                 Integer index = indexMap.get(type);
103                 if (index != null) {
104                         index++;        
105                 } else {
106                         if (reserved == null)
107                                 reserved = getAllModuleNamesForModel(g, composite);
108                         index = 0;
109                         while (true) {
110                                 String toTry = prefix + Integer.toString(index);
111                                 if (!reserved.contains(toTry))
112                                         break;
113                                 index++;
114                         }
115                         
116                 }
117                 indexMap.put(type, index);
118                 return prefix + index;
119         }
120         
121         private Set<String> getAllModuleNamesForModel(ReadGraph graph, final Resource res) throws DatabaseException {
122
123                 Resource model = DiagramUtils.getModel(graph, res);
124                 Resource configuration = DiagramUtils.getConfiguration(graph, model);
125                 Set<String> names = new HashSet<String>();
126                 if (configuration == null)
127                         return names;
128                 Collection<Resource> composites = getAllComposites(graph, configuration);
129                 for (Resource composite : composites) {
130                         names.addAll(getAllModuleNamesForComposite(graph, composite));
131                 }
132                 return names;
133         }
134         
135         protected abstract Resource getGraphicalCompositeType(ReadGraph graph) throws DatabaseException;
136         protected abstract Resource getFolderType(ReadGraph graph) throws DatabaseException;
137         
138         @SuppressWarnings("unchecked")
139         private Collection<Resource> getAllComposites(RequestProcessor processor, Resource configuration) throws DatabaseException {
140                 return (Set<Resource>)processor.syncRequest(new ResourceRead<Object>(configuration) {
141                         @Override
142                         public Object perform(ReadGraph graph) throws DatabaseException {
143                                 Layer0 l0 = Layer0.getInstance(graph);
144                                 Set<Resource> composites = new HashSet<Resource>();
145                                 Stack<Resource> resources = new Stack<Resource>();
146                                 Resource graphicalCompositeType = getGraphicalCompositeType(graph);
147                                 Resource folderType = getFolderType(graph);
148                                 resources.add(resource);
149                                 while (!resources.isEmpty()) {
150                                         Resource r = resources.pop();
151                                         if (graph.isInstanceOf(r, graphicalCompositeType)) {
152                                                 composites.add(r);
153                                         } else if (folderType != null && graph.isInstanceOf(r, folderType)){
154                                                 resources.addAll(graph.getObjects(r, l0.ConsistsOf));
155                                         }
156                                 }
157                                 return composites;
158                         }
159                 }, TransientCacheListener.instance());
160         }
161         
162         @SuppressWarnings("unchecked")
163         private Set<String> getAllModuleNamesForComposite(RequestProcessor processor, Resource composite) throws DatabaseException {
164                 return (Set<String>)processor.syncRequest(new ResourceRead<Object>(composite) {
165                         @Override
166                         public Object perform(ReadGraph graph) throws DatabaseException {
167                                 Layer0 l0 = Layer0.getInstance(graph);
168                                 Set<String> names = new HashSet<String>();
169                                 Collection<Resource> components = graph.getObjects(resource, l0.ConsistsOf);
170                                 for (Resource component : components) {
171                                         String n = graph.getPossibleRelatedValue(component, l0.HasName, Bindings.STRING);
172                                         if (n != null)
173                                                 names.add(n);
174                                 }
175                                 return names;
176                         }
177                 }, TransientCacheListener.instance());
178                 
179         }
180         
181         public Diagram<T> createDiagram(WriteGraph g,String name, Resource compositeType, Resource parent) throws DatabaseException {
182                 return createDiagram(g, name, null, null,compositeType, parent);
183         }
184         
185         
186         
187         /**
188          * Creates a new Diagram
189          * @param g
190          * @param name name of the diagram
191          * @param compositeType composite type of the diagram
192          * @param parent resource where diagram is added
193          * @return
194          * @throws DatabaseException
195          */
196         @SuppressWarnings("deprecation")
197         public Diagram<T> createDiagram(WriteGraph g,String name, DiagramDesc desc, Template tpl, Resource compositeType, Resource parent) throws DatabaseException {
198                 Layer0 l0 = Layer0.getInstance(g);
199                 Layer0X l0x = Layer0X.getInstance(g);
200                 ModelingResources m = ModelingResources.getInstance(g);
201                 
202                 // create composite
203                 Resource composite = g.newResource();
204                 g.claim(composite, l0.InstanceOf, compositeType);
205                 
206                 // create diagram
207                 Resource diagramType = getDiagramFromComposite(g, compositeType);
208                 
209                 Resource diagram = OrderedSetUtils.create(g, diagramType);
210                 
211                 g.claim(composite, m.CompositeToDiagram, diagram);
212                 
213                 // link to parent and set name
214                 g.claimLiteral(composite, l0.HasName, name);
215                 g.claim(composite, l0.PartOf, parent);
216                 
217                 // activate mapping
218                 Resource mapping = g.newResource();
219         g.claim(mapping, l0.InstanceOf, m.DiagramToCompositeMapping);
220         g.claim(diagram, l0x.HasTrigger, mapping);
221         
222         if (tpl != null) {
223                 Map<String,Object> params = new HashMap<String, Object>();
224                 params.put("diagram", diagram);
225                 tpl.apply(g, params);
226         }
227         
228         
229         // Make diagram part of a dummy container library attached to the parent
230         // composite if it's not already part of something.
231         // This gives the diagram a proper URI without connecting it directly to the composite with ConsistsOf.
232         // This would cause problems because a diagram is a structural composite/component also.
233         g.claimLiteral(diagram, l0.HasName, name, Bindings.STRING);
234         Resource container = g.newResource();
235         g.claim(container, l0.InstanceOf, null, l0.Library);
236         g.addLiteral(container, l0.HasName, l0.NameOf, l0.String, "__CONTAINER__", Bindings.STRING);
237         g.claim(container, l0.ConsistsOf, diagram);
238         g.claim(composite, l0.ConsistsOf, container);
239         
240         if (desc != null)
241                 DiagramGraphUtil.setDiagramDesc(g, diagram, desc);
242                 
243                 Diagram<T> diag = construct(g, composite, diagram);
244                 diag.compositeToDiagramMap = compositeToDiagramMap;
245                 compositeToDiagramMap.put(composite, diag);
246                 return diag;
247         }
248         
249         public Diagram<T> fromExisting(ReadGraph g, Resource diagram) throws DatabaseException {
250                 ModelingResources m = ModelingResources.getInstance(g);
251                 StructuralResource2 s = StructuralResource2.getInstance(g);
252                 Resource composite = null;
253                 if (g.isInstanceOf(diagram, s.Composite)) {
254                         composite = diagram;
255                         diagram = g.getPossibleObject(composite, m.CompositeToDiagram);
256                         if (diagram == null)
257                                 return null;
258                 } else {
259                         composite = g.getPossibleObject(diagram, m.DiagramToComposite);
260                         if (composite == null)
261                                 return null;
262                 }
263                 
264                 Diagram<T> diag = compositeToDiagramMap.get(composite);
265                 if (diag != null)
266                         return diag;
267                 
268                 diag =  construct(g,composite, diagram);
269                 diag.compositeToDiagramMap = compositeToDiagramMap;
270                 compositeToDiagramMap.put(composite, diag);
271                 return diag;
272         }
273         
274         
275         
276         
277         
278         /**
279          * Returns diagram type from composite type
280          * @param g
281          * @param compositeType
282          * @return diagram type
283          * @throws NoSingleResultException
284          * @throws ManyObjectsForFunctionalRelationException
285          * @throws ServiceException
286          */
287         public Resource getDiagramFromComposite(ReadGraph g, Resource compositeType) throws DatabaseException {
288                 ModelingResources m  = ModelingResources.getInstance(g);
289                 Collection<Resource> diagramTemplates = g.getAssertedObjects(compositeType, m.HasModelingTemplate);
290                 for (Resource diagramTemplate : diagramTemplates) {
291                         Resource diagramType = g.getPossibleObject(diagramTemplate, m.HasDiagramType);
292                         if (diagramType != null)
293                                 return diagramType;
294                                 
295                 }
296                 throw new RuntimeException("Cannot find diagramType for composite " + compositeType);
297         }
298         
299         
300
301         
302         /**
303          * Adds new symbol to a diagram
304          * @param g
305          * @param symbolType
306          * @return
307          * @throws DatabaseException
308          */
309         public T addSymbol(WriteGraph g, Resource symbolType) throws DatabaseException {
310                 return addSymbol(g, symbolType, 0, 0);
311         }
312         
313         /**
314          * Adds new symbol to a diagram
315          * @param g
316          * @param symbolType
317          * @param name
318          * @return
319          * @throws DatabaseException
320          */
321         public T addSymbol(WriteGraph g, Resource symbolType, String name) throws DatabaseException {
322                 return addSymbol(g, symbolType, name, 0, 0);
323         }
324         
325         /**
326          * Adds new symbol to a diagram
327          * @param g
328          * @param diagramConf Diagram configuration
329          * @param symbolType type of the new symbol
330          * @param x
331          * @param y
332          * @return configuration of the new Symbol
333          * @throws DatabaseException
334          */
335         public T addSymbol(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
336                 return addSymbol(g, symbolType,null,x,y);
337         }
338         
339         /**
340          * Adds new symbol to a diagram
341          * @param g
342          * @param elementType
343          * @param name
344          * @param x
345          * @param y
346          * @return
347          * @throws DatabaseException
348          */
349         public T addSymbol(WriteGraph g, Resource elementType, String name, double x, double y) throws DatabaseException {
350                 if (elementType == null)
351                         throw new NullPointerException("Element type is null");
352                 Layer0 l0 = Layer0.getInstance(g);
353
354                 DiagramResource d = DiagramResource.getInstance(g);
355                 ModelingResources m = ModelingResources.getInstance(g);
356                 
357                 Resource componentType = null;
358                 if (g.isInheritedFrom(elementType, d.DefinedElement))
359                         componentType = Symbol.getComponentTypeFromSymbolType(g, elementType);
360                 else {
361                         componentType = elementType;
362                         elementType = Symbol.getSymbolTypeFromComponentType(g,componentType);
363                 }
364                         
365                 
366                 Resource element = g.newResource();
367                 g.claim(element, l0.InstanceOf, elementType);
368
369                 Resource module = g.newResource();
370                 g.claim(module, l0.InstanceOf, componentType);
371                 
372                 g.claim(module, m.ComponentToElement, element);
373                 g.claim(module, m.Mapped, module);
374
375                 String id = generateName(g, componentType, name);
376                 g.claimLiteral(module, l0.HasName, id);
377                 g.claimLiteral(element, l0.HasName, id);
378                 
379                 OrderedSetUtils.add(g, this.diagram, element);
380                 g.claim(this.diagram, l0.ConsistsOf, element);
381                 g.claim(this.composite, l0.ConsistsOf, module);
382                 
383                 T s =  constructSymbol(g, element, module);
384                 s.setSymbolTranslation(g, x, y);
385                 
386                 elementToSymbolMap.put(element, s);
387                 return s;
388         }
389         
390         /**
391          * Returns a Symbol for given resource.
392          * @param g
393          * @param element Element or Component of the Symbol.
394          * @return
395          * @throws ManyObjectsForFunctionalRelationException
396          * @throws ServiceException
397          * @throws NoSingleResultException
398          */
399         public T getSymbol(ReadGraph g, Resource element) throws DatabaseException {
400                 ModelingResources mr = ModelingResources.getInstance(g);
401                 DiagramResource dr = DiagramResource.getInstance(g);
402                 if (g.isInstanceOf(element, dr.Element))
403                         return getSymbol(g, element, g.getPossibleObject(element, mr.ElementToComponent));
404                 else
405                         return getSymbol(g, g.getSingleObject(element, mr.ComponentToElement), element);
406         }
407         
408         /**
409          * Returns a Symbol for given resource.
410          * @param g
411          * @param element Element Resource of the Symbol.
412          * @param component Component  Resource of the symbol. 
413          * @return
414          */
415         public T getSymbol(ReadGraph g, Resource element, Resource component) throws DatabaseException {
416                 T s = elementToSymbolMap.get(element);
417                 if (s == null) {
418                         // TODO : check that symbol actually belongs to this diagram
419                         s = constructSymbol(g, element, component);
420                         elementToSymbolMap.put(element, s);
421                 } else {
422                         if (s.component == null)
423                                 s.component = component;
424                         else if (!s.component.equals(component)) {
425                                 // FIXME : ?
426                                 return constructSymbol(g, element, component);
427                         }
428                 }
429                 return s;
430         }
431         
432         /**
433          *  Adds new element to a diagram
434          * @param g
435          * @param symbolType type of the element.
436          * @param x
437          * @param y
438          * @return
439          * @throws DatabaseException
440          */
441         public T addElement(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
442                 Layer0 l0 = Layer0.getInstance(g);
443
444                 Resource element = g.newResource();
445                 g.claim(element, l0.InstanceOf, symbolType);
446                                 
447                 DiagramUtils.addElement(g, this, element);
448                 
449                 T s = constructSymbol(g,element,null);
450                 
451                 s.setSymbolTranslation(g, x, y);
452                 
453                 elementToSymbolMap.put(element, s);
454                 return s;
455         }
456         
457         public T getSingleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
458                 List<T> matching = getSymbol(g, symbolName);
459                 if (matching.size() == 1)
460                         return matching.get(0);
461                 if (matching.size() == 0)
462                         return null;
463                 throw new NoSingleResultException("There are multiple symbols with name '" + symbolName);
464         }
465         
466         public T getPossibleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
467                 List<T> matching = getSymbol(g, symbolName);
468                 if (matching.size() == 1)
469                         return matching.get(0);
470                 return null;
471         }
472         
473         /**
474          * Returns all symbols on the diagram
475          * @param g
476          * @return
477          * @throws DatabaseException
478          */
479         public List<T> getSymbols(ReadGraph g) throws DatabaseException {
480                 ModelingResources m = ModelingResources.getInstance(g);
481                 List<T> matching = new ArrayList<T>();
482                 for (Resource element : OrderedSetUtils.toList(g, diagram)) {
483                         Resource component = g.getPossibleObject(element, m.ElementToComponent);
484                         matching.add(getSymbol(g,element, component));
485                 }
486                 return matching;
487         }
488         
489         /**
490          * Returns symbols that have matching name.
491          * 
492          * Prioritizes L0.HasLabel over L0.HasName (If symbol has label, it is used for comparison).
493          * 
494          * ';' character acts as a splitter, allowing input parameter and a label contain multiple identifiers.
495          *
496          * All the splits  
497          * 
498          * @param g
499          * @param symbolName
500          * @return
501          * @throws DatabaseException
502          */
503         public List<T> getSymbol(ReadGraph g, String symbolName) throws DatabaseException {
504                 ModelingResources m = ModelingResources.getInstance(g);
505                 Layer0 b = Layer0.getInstance(g);
506                 List<T> matching = new ArrayList<T>();
507                 
508                 String splitId[] = symbolName.split(";");
509                 
510                 for (Resource element : OrderedSetUtils.toList(g, diagram)) {
511                         Resource component = g.getPossibleObject(element, m.ElementToComponent);
512                         if (component == null)
513                                 component = g.getPossibleObject(element, m.HasParentComponent);
514                         if (component == null)
515                                 continue;
516                         String label = g.getPossibleRelatedValue(component, b.HasLabel);
517                         String name = g.getRelatedValue(component, b.HasName);
518                         if (label != null) {
519                                 String splitLabel[] = label.split(";");
520                                 
521                                 boolean match = true;
522                                 for (int i = 0; i < splitId.length; i++) {
523                                         if(!Arrays.contains(splitLabel, splitId[i])) {
524                                                 match = false;
525                                                 break;
526                                         }
527                                 }
528                                 if (match) {
529                                         matching.add(getSymbol(g,element, component));
530                                 } else {
531                                         if (label.equals(symbolName) || name.equals(symbolName)) {
532                                                 matching.add(getSymbol(g,element, component));
533                                                 
534                                         }
535                                 }
536                                 
537                         } else {
538                                 for (String split : splitId) {
539                                         if (name.equals(split)) {
540                                                 matching.add(getSymbol(g,element, component));
541                                         }
542                                 }
543                                 
544                         }
545                 }
546                 return matching;
547         }
548         
549         /**
550          * Returns a single symbol matching given name and type. If matching symbol cannot be found, returns null.
551          * Throws a NoSingleResultException if the re are multiple symbols matching the criteria.
552          * 
553          * @param g
554          * @param symbolName
555          * @param symbolType
556          * @return 
557          * @throws DatabaseException
558          */
559         public T getSingleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
560                 List<T> matching = getSymbol(g, symbolName, symbolType);
561                 if (matching.size() == 1)
562                         return matching.get(0);
563                 if (matching.size() == 0)
564                         return null;
565                 throw new NoSingleResultException("There are multiple symbols with name '" + symbolName + "' and type " + symbolType);
566         }
567         
568         public T getPossibleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
569                 List<T> matching = getSymbol(g, symbolName, symbolType);
570                 if (matching.size() == 1)
571                         return matching.get(0);
572                 return null;
573         }
574         
575         /**
576          * Returns symbols matching given name and type. 
577          * 
578          * @param g
579          * @param symbolName
580          * @param symbolType
581          * @return 
582          * @throws DatabaseException
583          */
584         public List<T> getSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
585
586                 List<T> nameMatching = getSymbol(g, symbolName);
587                 List<T> matching = new ArrayList<T>();
588                 for (T s : nameMatching) {
589                         if ((g.isInstanceOf(s.getElement(), symbolType)||
590                                          g.isInstanceOf(s.getComponent(), symbolType))) {
591                                         matching.add(s);
592                                 }
593                 }
594                 return matching;
595         }
596         
597         public Symbol getFlag(ReadGraph g, Resource flagType, String symbolName, Resource symbolType) throws DatabaseException {
598                 Layer0 b = Layer0.getInstance(g);
599                 DiagramResource dr = DiagramResource.getInstance(g);
600                 List<Symbol> matching = new ArrayList<Symbol>();
601                 for (Resource flag : OrderedSetUtils.toList(g, diagram)) {
602                         if (!g.isInstanceOf(flag, dr.Flag))
603                                 continue;
604                         if (!g.getSingleObject(flag, dr.HasFlagType).equals(flagType))
605                                 continue;
606                         Symbol flagSymbol = getSymbol(g,flag, null);
607
608                         Symbol connectedSymbol = flagSymbol.getDiagramSingleConnected(g, dr.Flag_ConnectionPoint);
609                         Resource component = connectedSymbol.getComponent();
610                         if (component == null)
611                                 continue;
612                         String label = g.getPossibleRelatedValue(component, b.HasLabel);
613                         String name = g.getRelatedValue(component, b.HasName);
614                         if (label != null) {
615                                 String splitId[] = symbolName.split(";");
616                                 if (splitId.length > 1) {
617                                         String splitLabel[] = label.split(";");
618                                         boolean match = true;
619                                         for (int i = 0; i < splitId.length; i++) {
620                                                 if(!Arrays.contains(splitLabel, splitId[i])) {
621                                                         match = false;
622                                                         break;
623                                                 }
624                                         }
625                                         if (match) {
626                                                 if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
627                                                         g.isInstanceOf(component, symbolType)) {
628                                                         matching.add(getSymbol(g,flag, null));
629                                                 }
630                                                 
631                                         }
632                                 } else {
633                                         if (label.equals(symbolName) || name.equals(symbolName)) {
634                                                 if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
635                                                         g.isInstanceOf(component, symbolType)) {
636                                                         matching.add(getSymbol(g,flag, null));
637                                                 }
638                                                 
639                                         }
640                                 }
641                                 
642                         } else {
643                                 if (name.equals(symbolName)) {
644                                         if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
645                                                         g.isInstanceOf(component, symbolType)) {
646                                                 matching.add(getSymbol(g,flag, null));
647                                         }
648                                 }
649                                 
650                         }
651                 }
652                 if (matching.size() == 1)
653                         return matching.get(0);
654                 if (matching.size() == 0)
655                         return null;
656                 throw new NoSingleResultException("There are multiple flags connecting symbol with name '" + symbolName + "' and type " + symbolType);
657                 
658         }
659         
660         public PageDesc getPageDesc(ReadGraph g) throws DatabaseException {
661                 PageDesc pDesc = DiagramGraphUtil.getPageDesc(g, diagram, PageDesc.DEFAULT);
662                 return pDesc;
663         }
664         
665         @Override
666         public boolean equals(Object o) {
667                 if (o == null)
668                         return false;
669                 if (this.getClass() != o.getClass())
670                         return false;
671                 Diagram other = (Diagram)o;
672                 return diagram.equals(other.diagram);
673         }
674         
675         @Override
676         public int hashCode() {
677                 return diagram.hashCode();
678         }
679         
680         void merge(Symbol to, Symbol from) {
681                 Resource element = from.getElement();
682                 for (Symbol s : elementToSymbolMap.values()) {
683                         if (s.element.equals(element)) {
684                                 s.element = to.element;
685                                 s.component = to.component;
686                         }
687                 }
688                 from.element = to.element;
689                 from.component = to.component;
690         }
691         
692         /**
693          * Returns a model containing the diagram.
694          * @param g
695          * @return
696          * @throws DatabaseException
697          */
698         public Resource getModel(ReadGraph g) throws DatabaseException {
699                 Layer0 l0 = Layer0.getInstance(g);
700                 SimulationResource sim = SimulationResource.getInstance(g);
701                 Resource r = composite;
702                 while (true) {
703                         Resource parent = g.getSingleObject(r, l0.PartOf);
704                         if (g.isInstanceOf(parent, sim.Model))
705                                 return parent;
706                         r = parent;
707                 }
708         }
709         
710         
711         
712 }
713