1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.symbolcontribution;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
20 import java.util.TreeMap;
21 import java.util.TreeSet;
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;
30 * @author Tuukka Lehtonen
32 public class CompositeSymbolProviderFactory implements SymbolProviderFactory {
34 Collection<SymbolProviderFactory> factories;
36 public CompositeSymbolProviderFactory(Collection<SymbolProviderFactory> factories) {
37 if (factories == null)
38 throw new NullPointerException("null factories");
39 this.factories = factories;
43 public int hashCode() {
44 return factories.hashCode();
48 public boolean equals(Object obj) {
53 if (getClass() != obj.getClass())
55 CompositeSymbolProviderFactory other = (CompositeSymbolProviderFactory) obj;
56 return factories.equals(other.factories);
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);
66 return new CompositeSymbolProvider(providers);
69 static class CompositeSymbolProvider extends AbstractSymbolProvider {
71 Collection<ISymbolProvider> providers;
73 public CompositeSymbolProvider(Collection<ISymbolProvider> providers) {
74 this.providers = providers;
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))
90 groupsByName.add(name, group);
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();
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)
106 groups.put(name, cgroup);
109 return new ArrayList<ISymbolGroup>(groups.values());
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() );
122 private String combineDescriptions(List<ISymbolGroup> grps) {
123 Set<String> descs = new TreeSet<String>();
124 for (ISymbolGroup grp : grps)
125 descs.add(grp.getDescription());
128 if (descs.size() == 1)
129 return descs.iterator().next();
130 return EString.implode(descs);
134 public void setListener(Runnable listener) {
135 for (ISymbolProvider provider : providers)
136 provider.setListener(listener);