704ffda0ed6f0e18acbe08512f05aaadbb455fa2
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / symbolcontribution / BasicSymbolProviderFactory.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.Collections;
17 import java.util.Comparator;
18
19 import org.simantics.databoard.Bindings;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.common.request.BinaryRead;
23 import org.simantics.db.common.request.ObjectsWithSupertype;
24 import org.simantics.db.common.utils.NameUtils;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.diagram.stubs.DiagramResource;
27 import org.simantics.diagram.symbollibrary.ISymbolGroup;
28 import org.simantics.diagram.symbollibrary.ISymbolItem;
29 import org.simantics.layer0.Layer0;
30
31 /**
32  * A basic SymbolProviderFactory implementation for the graph database. It is
33  * capable of loading an ISymbolProvider from BasicSymbolContribution instances
34  * like the following:
35  * 
36  * <pre>
37  * _ : DIA.BasicSymbolContribution
38  *     DIA.BasicSymbolContributionHasSymbolLibrary
39  *         MySymbolLibrary1
40  *         MySymbolLibrary2
41  * </pre>
42  * 
43  * @author Tuukka Lehtonen
44  */
45 public class BasicSymbolProviderFactory implements SymbolProviderFactory {
46                 
47     Resource contribution;
48     Resource diagram;
49
50     public BasicSymbolProviderFactory(Resource contribution, Resource diagram) {
51         this.contribution = contribution;
52         this.diagram = diagram;
53     }
54
55         @Override
56         public int hashCode() {
57                 final int prime = 31;
58                 int result = 1;
59                 result = prime * result + ((contribution == null) ? 0 : contribution.hashCode());
60                 result = prime * result + ((diagram == null) ? 0 : diagram.hashCode());
61                 return result;
62         }
63
64         @Override
65         public boolean equals(Object obj) {
66                 if (this == obj)
67                         return true;
68                 if (obj == null)
69                         return false;
70                 if (getClass() != obj.getClass())
71                         return false;
72                 BasicSymbolProviderFactory other = (BasicSymbolProviderFactory) obj;
73                 if (contribution == null) {
74                         if (other.contribution != null)
75                                 return false;
76                 } else if (!contribution.equals(other.contribution))
77                         return false;
78                 if (diagram == null) {
79                         if (other.diagram != null)
80                                 return false;
81                 } else if (!diagram.equals(other.diagram))
82                         return false;
83                 return true;
84         }
85     
86     @Override
87     public ISymbolProvider create(ReadGraph g) throws DatabaseException {
88         return g.syncRequest(new LoadRequest(contribution, diagram));
89     }
90
91     /*
92      * Note: this cannot be ResourceRead since it must never be
93      * classified as immutable because of possible dynamic filters
94      */
95     static class LoadRequest extends BinaryRead<Resource, Resource, ISymbolProvider> {
96         public LoadRequest(Resource contribution, Resource diagram) {
97             super(contribution, diagram);
98         }
99         @Override
100         public ISymbolProvider perform(ReadGraph graph) throws DatabaseException {
101             Layer0 l0 = Layer0.getInstance(graph);
102             DiagramResource dr = DiagramResource.getInstance(graph);
103
104             if (!SymbolProviderFactories.accept(graph, dr, parameter, parameter2))
105                 return new SymbolProvider(Collections.<ISymbolGroup>emptyList());
106
107             Collection<Resource> libraries = graph.getObjects(parameter, dr.BasicSymbolContributionHasSymbolLibrary);
108             Collection<ISymbolGroup> groups = new ArrayList<ISymbolGroup>(libraries.size());
109
110             for (Resource library : libraries) {
111                 if (SymbolProviderFactories.accept(graph, dr, library, parameter2)) {
112                     groups.add(createGroup(graph, library, l0.DependsOn, parameter2));
113                 }
114             }
115
116             return new SymbolProvider(groups);
117             
118         }
119     }
120
121     static class SymbolProvider extends AbstractSymbolProvider {
122         public SymbolProvider(Collection<ISymbolGroup> groups) {
123             super();
124             setSymbolGroup(groups);
125             lockGroups();
126         }
127     }
128
129     static SymbolGroup createGroup(ReadGraph graph, Resource library, Resource relation, Resource diagram) throws DatabaseException {
130         Layer0 l0 = Layer0.getInstance(graph);
131         DiagramResource dr = DiagramResource.getInstance(graph);
132
133         String name = safeName(graph, library);
134         String description = graph.getPossibleRelatedValue2(library, l0.HasDescription, Bindings.STRING);
135         if (description == null)
136             description = name;
137         ModifiableSymbolGroup group = new ModifiableSymbolGroup(library, name, description);
138
139         ArrayList<ISymbolItem> items = new ArrayList<ISymbolItem>();
140         for (Resource item : graph.syncRequest(new ObjectsWithSupertype(library, relation, dr.Element))) {
141             if (!SymbolProviderFactories.accept(graph, dr, item, diagram)) {
142                 continue;
143             }
144
145             String itemName = safeName(graph, item);
146             String itemDescription = graph.getPossibleRelatedValue2(item, l0.HasDescription, Bindings.STRING);
147             if (itemDescription == null || itemDescription.isEmpty())
148                 itemDescription = itemName;
149             items.add( new ElementSymbolItem(item, itemName, itemDescription, group) );
150         }
151
152         Collections.sort(items, new Comparator<ISymbolItem>() {
153             @Override
154             public int compare(ISymbolItem o1, ISymbolItem o2) {
155                 return o1.getName().compareToIgnoreCase(o2.getName());
156             }
157         });
158
159         group.setItems(items.toArray(new ISymbolItem[items.size()]));
160
161         return group;
162     }
163
164     private static String safeName(ReadGraph graph, Resource r) throws DatabaseException {
165         Layer0 L0 = Layer0.getInstance(graph);
166         String name = graph.getPossibleRelatedValue2(r, L0.HasLabel, Bindings.STRING);
167         if (name == null || name.isEmpty())
168             name = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);
169         if (name == null)
170             name = NameUtils.getSafeName(graph, r);
171         return name;
172     }
173
174 }