]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/symbolcontribution/CompositeSymbolProviderFactory.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / symbolcontribution / CompositeSymbolProviderFactory.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.diagram.symbolcontribution;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.TreeMap;
21 import java.util.TreeSet;
22
23 import org.simantics.db.ReadGraph;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.diagram.symbollibrary.ISymbolGroup;
26 import org.simantics.utils.datastructures.MapList;
27 import org.simantics.utils.strings.EString;
28
29 /**
30  * @author Tuukka Lehtonen
31  */
32 public class CompositeSymbolProviderFactory implements SymbolProviderFactory {
33
34     Collection<SymbolProviderFactory> factories;
35
36     public CompositeSymbolProviderFactory(Collection<SymbolProviderFactory> factories) {
37         if (factories == null)
38             throw new NullPointerException("null factories");
39         this.factories = factories;
40     }
41
42     @Override
43     public int hashCode() {
44         return factories.hashCode();
45     }
46
47     @Override
48     public boolean equals(Object obj) {
49         if (this == obj)
50             return true;
51         if (obj == null)
52             return false;
53         if (getClass() != obj.getClass())
54             return false;
55         CompositeSymbolProviderFactory other = (CompositeSymbolProviderFactory) obj;
56         return factories.equals(other.factories);
57     }
58
59     @Override
60     public ISymbolProvider create(ReadGraph graph) throws DatabaseException {
61         ArrayList<ISymbolProvider> providers = new ArrayList<ISymbolProvider>(factories.size());
62         for (SymbolProviderFactory factory : factories) {
63             ISymbolProvider provider = factory.create(graph);
64             providers.add(provider);
65         }
66         return new CompositeSymbolProvider(providers);
67     }
68
69     static class CompositeSymbolProvider extends AbstractSymbolProvider {
70
71         Collection<ISymbolProvider> providers;
72
73         public CompositeSymbolProvider(Collection<ISymbolProvider> providers) {
74             this.providers = providers;
75         }
76
77         @Override
78         public Collection<ISymbolGroup> getSymbolGroups() {
79             MapList<String, ISymbolGroup> groupsByName = new MapList<String, ISymbolGroup>();
80             Set<Object> processedIds = new HashSet<Object>();
81             Map<String, ISymbolGroup> groups = new TreeMap<String, ISymbolGroup>();
82             for(ISymbolProvider provider : providers) {
83                 for(ISymbolGroup group : provider.getSymbolGroups()) {
84                     String name = group.getName();
85                     if (group instanceof IIdentifiedObject) {
86                         Object id = ((IIdentifiedObject) group).getId();
87                         if (!processedIds.add(id))
88                             continue;
89                     }
90                     groupsByName.add(name, group);
91                 }
92             }
93             // Process groups with multiple ISymbolGroup contributions
94             // into CompositeSymbolGroupsand leave single ISymbolGroups as such.
95             for (String name : groupsByName.getKeys()) {
96                 List<ISymbolGroup> grps = groupsByName.getValues(name);
97                 int grpCount = grps.size();
98                 if (grpCount == 1) {
99                     groups.put(name, grps.get(0));
100                 } else if (grpCount > 1) {
101                     Object id = combineIdentification(grps);
102                     String description = combineDescriptions(grps);
103                     CompositeSymbolGroup cgroup = new CompositeSymbolGroup(id, name, description);
104                     for (ISymbolGroup grp : grps)
105                         cgroup.add(grp);
106                     groups.put(name, cgroup);
107                 }
108             }
109             return new ArrayList<ISymbolGroup>(groups.values());
110         }
111
112         private Object combineIdentification(List<ISymbolGroup> grps) {
113             Set<Object> id = new HashSet<Object>();
114             for (ISymbolGroup grp : grps) {
115                 if (grp instanceof IIdentifiedObject) { 
116                     id.add( ((IIdentifiedObject) grp).getId() );
117                 }
118             }
119             return id;
120         }
121
122         private String combineDescriptions(List<ISymbolGroup> grps) {
123             Set<String> descs = new TreeSet<String>();
124             for (ISymbolGroup grp : grps)
125                 descs.add(grp.getDescription());
126             if (descs.isEmpty())
127                 return "";
128             if (descs.size() == 1)
129                 return descs.iterator().next();
130             return EString.implode(descs);
131         }
132
133         @Override
134         public void setListener(Runnable listener) {
135             for (ISymbolProvider provider : providers)
136                 provider.setListener(listener);
137         }
138
139     }
140
141 }