]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.diagram/src/org/simantics/interop/diagram/Diagram.java
365cde242a5e1bea827e1fcdd8ce3612cccd6bfd
[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                 DiagramResource dia = DiagramResource.getInstance(g);
202                 
203                 // create composite
204                 Resource composite = g.newResource();
205                 g.claim(composite, l0.InstanceOf, compositeType);
206                 
207                 // create diagram
208                 Resource diagramType = getDiagramFromComposite(g, compositeType);
209                 
210                 Resource diagram = OrderedSetUtils.create(g, diagramType);
211                 
212                 g.claim(composite, m.CompositeToDiagram, diagram);
213                 
214                 // link to parent and set name
215                 g.claimLiteral(composite, l0.HasName, name);
216                 g.claim(composite, l0.PartOf, parent);
217                 
218                 // activate mapping
219                 Resource mapping = g.newResource();
220         g.claim(mapping, l0.InstanceOf, m.DiagramToCompositeMapping);
221         g.claim(diagram, l0x.HasTrigger, mapping);
222         
223         if (tpl != null) {
224                 Map<String,Object> params = new HashMap<String, Object>();
225                 params.put("diagram", diagram);
226                 tpl.apply(g, params);
227         }
228         
229         
230         // Make diagram part of a dummy container library attached to the parent
231         // composite if it's not already part of something.
232         // This gives the diagram a proper URI without connecting it directly to the composite with ConsistsOf.
233         // This would cause problems because a diagram is a structural composite/component also.
234         g.claimLiteral(diagram, l0.HasName, name, Bindings.STRING);
235         Resource container = g.newResource();
236         g.claim(container, l0.InstanceOf, null, dia.DiagramContainer);
237         g.addLiteral(container, l0.HasName, l0.NameOf, l0.String, "__CONTAINER__", Bindings.STRING);
238         g.claim(container, l0.ConsistsOf, diagram);
239         g.claim(composite, l0.ConsistsOf, container);
240         
241         if (desc != null)
242                 DiagramGraphUtil.setDiagramDesc(g, diagram, desc);
243                 
244                 Diagram<T> diag = construct(g, composite, diagram);
245                 diag.compositeToDiagramMap = compositeToDiagramMap;
246                 compositeToDiagramMap.put(composite, diag);
247                 return diag;
248         }
249         
250         public Diagram<T> fromExisting(ReadGraph g, Resource diagram) throws DatabaseException {
251                 ModelingResources m = ModelingResources.getInstance(g);
252                 StructuralResource2 s = StructuralResource2.getInstance(g);
253                 DiagramResource d = DiagramResource.getInstance(g);
254                 Resource composite = null;
255                 if (g.isInstanceOf(diagram, s.Composite)) {
256                         composite = diagram;
257                         diagram = g.getPossibleObject(composite, m.CompositeToDiagram);
258                         if (diagram == null)
259                                 return null;
260                 } else if (g.isInheritedFrom(diagram, d.DefinedElement)) {
261                         // TODO : Defined Element behaves differently to regular configuration diagrams; should we have separate implementation?
262                         composite = diagram;
263                         diagram = g.getPossibleObject(composite, s.IsDefinedBy);
264                         if (diagram == null)
265                                 return null;
266                 } else {
267                         composite = g.getPossibleObject(diagram, m.DiagramToComposite);
268                         if (composite == null)
269                                 return null;
270                 }
271                 
272                 Diagram<T> diag = compositeToDiagramMap.get(composite);
273                 if (diag != null)
274                         return diag;
275                 
276                 diag =  construct(g,composite, diagram);
277                 diag.compositeToDiagramMap = compositeToDiagramMap;
278                 compositeToDiagramMap.put(composite, diag);
279                 return diag;
280         }
281         
282         
283         
284         
285         
286         
287         
288         /**
289          * Returns diagram type from composite type
290          * @param g
291          * @param compositeType
292          * @return diagram type
293          * @throws NoSingleResultException
294          * @throws ManyObjectsForFunctionalRelationException
295          * @throws ServiceException
296          */
297         public Resource getDiagramFromComposite(ReadGraph g, Resource compositeType) throws DatabaseException {
298                 ModelingResources m  = ModelingResources.getInstance(g);
299                 Collection<Resource> diagramTemplates = g.getAssertedObjects(compositeType, m.HasModelingTemplate);
300                 for (Resource diagramTemplate : diagramTemplates) {
301                         Resource diagramType = g.getPossibleObject(diagramTemplate, m.HasDiagramType);
302                         if (diagramType != null)
303                                 return diagramType;
304                                 
305                 }
306                 throw new RuntimeException("Cannot find diagramType for composite " + compositeType);
307         }
308         
309         
310
311         
312         /**
313          * Adds new symbol to a diagram
314          * @param g
315          * @param symbolType
316          * @return
317          * @throws DatabaseException
318          */
319         public T addSymbol(WriteGraph g, Resource symbolType) throws DatabaseException {
320                 return addSymbol(g, symbolType, 0, 0);
321         }
322         
323         /**
324          * Adds new symbol to a diagram
325          * @param g
326          * @param symbolType
327          * @param name
328          * @return
329          * @throws DatabaseException
330          */
331         public T addSymbol(WriteGraph g, Resource symbolType, String name) throws DatabaseException {
332                 return addSymbol(g, symbolType, name, 0, 0);
333         }
334         
335         /**
336          * Adds new symbol to a diagram
337          * @param g
338          * @param diagramConf Diagram configuration
339          * @param symbolType type of the new symbol
340          * @param x
341          * @param y
342          * @return configuration of the new Symbol
343          * @throws DatabaseException
344          */
345         public T addSymbol(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
346                 return addSymbol(g, symbolType,null,x,y);
347         }
348         
349         /**
350          * Adds new symbol to a diagram
351          * @param g
352          * @param elementType
353          * @param name
354          * @param x
355          * @param y
356          * @return
357          * @throws DatabaseException
358          */
359         public T addSymbol(WriteGraph g, Resource elementType, String name, double x, double y) throws DatabaseException {
360                 if (elementType == null)
361                         throw new NullPointerException("Element type is null");
362                 Layer0 l0 = Layer0.getInstance(g);
363
364                 DiagramResource d = DiagramResource.getInstance(g);
365                 ModelingResources m = ModelingResources.getInstance(g);
366                 
367                 Resource componentType = null;
368                 if (g.isInheritedFrom(elementType, d.DefinedElement))
369                         componentType = Symbol.getComponentTypeFromSymbolType(g, elementType);
370                 else {
371                         componentType = elementType;
372                         elementType = Symbol.getSymbolTypeFromComponentType(g,componentType);
373                 }
374                         
375                 
376                 Resource element = g.newResource();
377                 g.claim(element, l0.InstanceOf, elementType);
378
379                 Resource module = g.newResource();
380                 g.claim(module, l0.InstanceOf, componentType);
381                 
382                 g.claim(module, m.ComponentToElement, element);
383                 g.claim(module, m.Mapped, module);
384
385                 String id = generateName(g, componentType, name);
386                 g.claimLiteral(module, l0.HasName, id);
387                 g.claimLiteral(element, l0.HasName, id);
388                 
389                 OrderedSetUtils.add(g, this.diagram, element);
390                 g.claim(this.diagram, l0.ConsistsOf, element);
391                 g.claim(this.composite, l0.ConsistsOf, module);
392                 
393                 T s =  constructSymbol(g, element, module);
394                 s.setSymbolTranslation(g, x, y);
395                 
396                 elementToSymbolMap.put(element, s);
397                 return s;
398         }
399         
400         /**
401          * Returns a Symbol for given resource.
402          * @param g
403          * @param element Element or Component of the Symbol.
404          * @return
405          * @throws ManyObjectsForFunctionalRelationException
406          * @throws ServiceException
407          * @throws NoSingleResultException
408          */
409         public T getSymbol(ReadGraph g, Resource element) throws DatabaseException {
410                 ModelingResources mr = ModelingResources.getInstance(g);
411                 DiagramResource dr = DiagramResource.getInstance(g);
412                 StructuralResource2 s = StructuralResource2.getInstance(g);
413                 if (g.isInstanceOf(element, dr.Element))
414                         return getSymbol(g, element, g.getPossibleObject(element, mr.ElementToComponent));
415                 else if (g.isSubrelationOf(element, s.IsConnectedTo)) {
416                         // TODO : Defined Element
417                         return getSymbol(g, g.getSingleObject(element, dr.HasConnectionPoint_Inverse),element);
418                 }
419                 else
420                         return getSymbol(g, g.getSingleObject(element, mr.ComponentToElement), element);
421         }
422         
423         /**
424          * Returns a Symbol for given resource.
425          * @param g
426          * @param element Element Resource of the Symbol.
427          * @param component Component  Resource of the symbol. 
428          * @return
429          */
430         public T getSymbol(ReadGraph g, Resource element, Resource component) throws DatabaseException {
431                 T s = elementToSymbolMap.get(element);
432                 if (s == null) {
433                         // TODO : check that symbol actually belongs to this diagram
434                         s = constructSymbol(g, element, component);
435                         elementToSymbolMap.put(element, s);
436                 } else {
437                         if (s.component == null)
438                                 s.component = component;
439                         else if (!s.component.equals(component)) {
440                                 // FIXME : ?
441                                 return constructSymbol(g, element, component);
442                         }
443                 }
444                 return s;
445         }
446         
447         /**
448          *  Adds new element to a diagram
449          * @param g
450          * @param symbolType type of the element.
451          * @param x
452          * @param y
453          * @return
454          * @throws DatabaseException
455          */
456         public T addElement(WriteGraph g, Resource symbolType, double x, double y) throws DatabaseException {
457                 Layer0 l0 = Layer0.getInstance(g);
458
459                 Resource element = g.newResource();
460                 g.claim(element, l0.InstanceOf, symbolType);
461                                 
462                 DiagramUtils.addElement(g, this, element);
463                 
464                 T s = constructSymbol(g,element,null);
465                 
466                 s.setSymbolTranslation(g, x, y);
467                 
468                 elementToSymbolMap.put(element, s);
469                 return s;
470         }
471         
472         public T getSingleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
473                 List<T> matching = getSymbol(g, symbolName);
474                 if (matching.size() == 1)
475                         return matching.get(0);
476                 if (matching.size() == 0)
477                         return null;
478                 throw new NoSingleResultException("There are multiple symbols with name '" + symbolName);
479         }
480         
481         public T getPossibleSymbol(ReadGraph g, String symbolName) throws DatabaseException {
482                 List<T> matching = getSymbol(g, symbolName);
483                 if (matching.size() == 1)
484                         return matching.get(0);
485                 return null;
486         }
487         
488         /**
489          * Returns all symbols on the diagram
490          * @param g
491          * @return
492          * @throws DatabaseException
493          */
494         public List<T> getSymbols(ReadGraph g) throws DatabaseException {
495                 ModelingResources m = ModelingResources.getInstance(g);
496                 List<T> matching = new ArrayList<T>();
497                 for (Resource element : OrderedSetUtils.toList(g, diagram)) {
498                         Resource component = g.getPossibleObject(element, m.ElementToComponent);
499                         matching.add(getSymbol(g,element, component));
500                 }
501                 return matching;
502         }
503         
504         /**
505          * Returns symbols that have matching name.
506          * 
507          * Prioritizes L0.HasLabel over L0.HasName (If symbol has label, it is used for comparison).
508          * 
509          * ';' character acts as a splitter, allowing input parameter and a label contain multiple identifiers.
510          *
511          * All the splits  
512          * 
513          * @param g
514          * @param symbolName
515          * @return
516          * @throws DatabaseException
517          */
518         public List<T> getSymbol(ReadGraph g, String symbolName) throws DatabaseException {
519                 ModelingResources m = ModelingResources.getInstance(g);
520                 Layer0 b = Layer0.getInstance(g);
521                 List<T> matching = new ArrayList<T>();
522                 
523                 String splitId[] = symbolName.split(";");
524                 
525                 for (Resource element : OrderedSetUtils.toList(g, diagram)) {
526                         Resource component = g.getPossibleObject(element, m.ElementToComponent);
527                         if (component == null)
528                                 component = g.getPossibleObject(element, m.HasParentComponent);
529                         if (component == null)
530                                 continue;
531                         String label = g.getPossibleRelatedValue(component, b.HasLabel);
532                         String name = g.getRelatedValue(component, b.HasName);
533                         if (label != null) {
534                                 String splitLabel[] = label.split(";");
535                                 
536                                 boolean match = true;
537                                 for (int i = 0; i < splitId.length; i++) {
538                                         if(!Arrays.contains(splitLabel, splitId[i])) {
539                                                 match = false;
540                                                 break;
541                                         }
542                                 }
543                                 if (match) {
544                                         matching.add(getSymbol(g,element, component));
545                                 } else {
546                                         if (label.equals(symbolName) || name.equals(symbolName)) {
547                                                 matching.add(getSymbol(g,element, component));
548                                                 
549                                         }
550                                 }
551                                 
552                         } else {
553                                 for (String split : splitId) {
554                                         if (name.equals(split)) {
555                                                 matching.add(getSymbol(g,element, component));
556                                         }
557                                 }
558                                 
559                         }
560                 }
561                 return matching;
562         }
563         
564         /**
565          * Returns a single symbol matching given name and type. If matching symbol cannot be found, returns null.
566          * Throws a NoSingleResultException if the re are multiple symbols matching the criteria.
567          * 
568          * @param g
569          * @param symbolName
570          * @param symbolType
571          * @return 
572          * @throws DatabaseException
573          */
574         public T getSingleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
575                 List<T> matching = getSymbol(g, symbolName, symbolType);
576                 if (matching.size() == 1)
577                         return matching.get(0);
578                 if (matching.size() == 0)
579                         return null;
580                 throw new NoSingleResultException("There are multiple symbols with name '" + symbolName + "' and type " + symbolType);
581         }
582         
583         public T getPossibleSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
584                 List<T> matching = getSymbol(g, symbolName, symbolType);
585                 if (matching.size() == 1)
586                         return matching.get(0);
587                 return null;
588         }
589         
590         /**
591          * Returns symbols matching given name and type. 
592          * 
593          * @param g
594          * @param symbolName
595          * @param symbolType
596          * @return 
597          * @throws DatabaseException
598          */
599         public List<T> getSymbol(ReadGraph g, String symbolName, Resource symbolType) throws DatabaseException {
600
601                 List<T> nameMatching = getSymbol(g, symbolName);
602                 List<T> matching = new ArrayList<T>();
603                 for (T s : nameMatching) {
604                         if ((g.isInstanceOf(s.getElement(), symbolType)||
605                                          g.isInstanceOf(s.getComponent(), symbolType))) {
606                                         matching.add(s);
607                                 }
608                 }
609                 return matching;
610         }
611         
612         public Symbol getFlag(ReadGraph g, Resource flagType, String symbolName, Resource symbolType) throws DatabaseException {
613                 Layer0 b = Layer0.getInstance(g);
614                 DiagramResource dr = DiagramResource.getInstance(g);
615                 List<Symbol> matching = new ArrayList<Symbol>();
616                 for (Resource flag : OrderedSetUtils.toList(g, diagram)) {
617                         if (!g.isInstanceOf(flag, dr.Flag))
618                                 continue;
619                         if (!g.getSingleObject(flag, dr.HasFlagType).equals(flagType))
620                                 continue;
621                         Symbol flagSymbol = getSymbol(g,flag, null);
622
623                         Symbol connectedSymbol = flagSymbol.getDiagramSingleConnected(g, dr.Flag_ConnectionPoint);
624                         Resource component = connectedSymbol.getComponent();
625                         if (component == null)
626                                 continue;
627                         String label = g.getPossibleRelatedValue(component, b.HasLabel);
628                         String name = g.getRelatedValue(component, b.HasName);
629                         if (label != null) {
630                                 String splitId[] = symbolName.split(";");
631                                 if (splitId.length > 1) {
632                                         String splitLabel[] = label.split(";");
633                                         boolean match = true;
634                                         for (int i = 0; i < splitId.length; i++) {
635                                                 if(!Arrays.contains(splitLabel, splitId[i])) {
636                                                         match = false;
637                                                         break;
638                                                 }
639                                         }
640                                         if (match) {
641                                                 if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
642                                                         g.isInstanceOf(component, symbolType)) {
643                                                         matching.add(getSymbol(g,flag, null));
644                                                 }
645                                                 
646                                         }
647                                 } else {
648                                         if (label.equals(symbolName) || name.equals(symbolName)) {
649                                                 if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
650                                                         g.isInstanceOf(component, symbolType)) {
651                                                         matching.add(getSymbol(g,flag, null));
652                                                 }
653                                                 
654                                         }
655                                 }
656                                 
657                         } else {
658                                 if (name.equals(symbolName)) {
659                                         if (g.isInstanceOf(connectedSymbol.getElement(), symbolType)||
660                                                         g.isInstanceOf(component, symbolType)) {
661                                                 matching.add(getSymbol(g,flag, null));
662                                         }
663                                 }
664                                 
665                         }
666                 }
667                 if (matching.size() == 1)
668                         return matching.get(0);
669                 if (matching.size() == 0)
670                         return null;
671                 throw new NoSingleResultException("There are multiple flags connecting symbol with name '" + symbolName + "' and type " + symbolType);
672                 
673         }
674         
675         public PageDesc getPageDesc(ReadGraph g) throws DatabaseException {
676                 PageDesc pDesc = DiagramGraphUtil.getPageDesc(g, diagram, PageDesc.DEFAULT);
677                 return pDesc;
678         }
679         
680         @Override
681         public boolean equals(Object o) {
682                 if (o == null)
683                         return false;
684                 if (this.getClass() != o.getClass())
685                         return false;
686                 Diagram other = (Diagram)o;
687                 return diagram.equals(other.diagram);
688         }
689         
690         @Override
691         public int hashCode() {
692                 return diagram.hashCode();
693         }
694         
695         void merge(Symbol to, Symbol from) {
696                 Resource element = from.getElement();
697                 for (Symbol s : elementToSymbolMap.values()) {
698                         if (s.element.equals(element)) {
699                                 s.element = to.element;
700                                 s.component = to.component;
701                         }
702                 }
703                 from.element = to.element;
704                 from.component = to.component;
705         }
706         
707         /**
708          * Returns a model containing the diagram.
709          * @param g
710          * @return
711          * @throws DatabaseException
712          */
713         public Resource getModel(ReadGraph g) throws DatabaseException {
714                 Layer0 l0 = Layer0.getInstance(g);
715                 SimulationResource sim = SimulationResource.getInstance(g);
716                 Resource r = composite;
717                 while (true) {
718                         Resource parent = g.getSingleObject(r, l0.PartOf);
719                         if (g.isInstanceOf(parent, sim.Model))
720                                 return parent;
721                         r = parent;
722                 }
723         }
724         
725         
726         
727 }
728