Better support for ontological profiles
[simantics/platform.git] / bundles / org.simantics.diagram.profile / src / org / simantics / diagram / profile / function / All.java
1 package org.simantics.diagram.profile.function;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.TreeMap;
10
11 import org.eclipse.swt.SWT;
12 import org.eclipse.swt.widgets.Event;
13 import org.eclipse.swt.widgets.Tree;
14 import org.eclipse.swt.widgets.TreeItem;
15 import org.simantics.Simantics;
16 import org.simantics.browsing.ui.BuiltinKeys;
17 import org.simantics.browsing.ui.GraphExplorer;
18 import org.simantics.browsing.ui.NodeContext;
19 import org.simantics.databoard.Bindings;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.WriteGraph;
23 import org.simantics.db.common.request.WriteRequest;
24 import org.simantics.db.common.utils.ListUtils;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.db.layer0.adapter.Instances;
27 import org.simantics.db.layer0.variable.Variable;
28 import org.simantics.db.service.VirtualGraphSupport;
29 import org.simantics.diagram.profile.view.ResourcePair;
30 import org.simantics.diagram.stubs.DiagramResource;
31 import org.simantics.layer0.Layer0;
32 import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;
33 import org.simantics.scenegraph.profile.ProfileUtils;
34 import org.simantics.scl.reflection.annotations.SCLValue;
35 import org.simantics.scl.runtime.function.FunctionImpl1;
36 import org.simantics.scl.runtime.tuple.Tuple;
37 import org.simantics.scl.runtime.tuple.Tuple2;
38 import org.simantics.simulation.ontology.SimulationResource;
39 import org.simantics.utils.strings.StringUtils;
40
41 public class All {
42
43     @SCLValue(type = "ReadGraph -> Resource -> Resource -> [Resource]")
44     public static List<Resource> profileChildren(ReadGraph graph, Resource resource, Resource context) throws DatabaseException {
45         Layer0 L0 = Layer0.getInstance(graph);
46         List<Resource> listedChildren = ListUtils.toList(graph, context);
47         if(listedChildren.isEmpty()) {
48                 DiagramResource DIA = DiagramResource.getInstance(graph);
49                 TreeMap<Double,Resource> priorityChildren = new TreeMap<Double,Resource>();
50                 for(Resource child : graph.getObjects(context, L0.IsComposedOf)) {
51                         Double p = graph.getPossibleRelatedValue(child, DIA.Profile_priority, Bindings.DOUBLE);
52                         if(p != null)
53                                 priorityChildren.put(p, child);
54                 }
55                         return new ArrayList<Resource>(priorityChildren.values());
56         } else {
57                 return listedChildren;
58         }
59     }
60
61     @SCLValue(type = "ReadGraph -> Resource -> Variable -> [(String, Resource)]")
62     public static List<Tuple> availableProfiles(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
63         
64         Resource runtimeDiagram = ScenegraphLoaderUtils.getPossibleResourceSelection(graph, context);
65         if(runtimeDiagram == null) return Collections.emptyList();
66
67         Layer0 L0 = Layer0.getInstance(graph);
68         DiagramResource DIA = DiagramResource.getInstance(graph);
69
70         String modelURI = graph.getPossibleRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasModelURI);
71         if (modelURI == null)
72             return Collections.emptyList();
73
74         Resource model = graph.getPossibleResource(modelURI);
75         if (model == null)
76             return Collections.emptyList();
77
78         Instances query = graph.adapt(DIA.Profile, Instances.class);
79
80         ArrayList<Tuple> result = new ArrayList<Tuple>();
81         for(Resource profile : query.find(graph, model)) {
82             if(!graph.hasStatement(profile, L0.Abstract)) {
83                 String name = graph.getRelatedValue(profile, L0.HasName, Bindings.STRING);
84                 result.add(new Tuple2(name, profile));
85             }
86         }
87         return result;
88         
89     }
90
91     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
92     public static Object profileEntrySelected(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
93         
94         return new FunctionImpl1<Object, Boolean>() {
95
96                 public void processRecursively(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry, boolean checked) throws DatabaseException {
97
98                 DiagramResource DIA = DiagramResource.getInstance(graph);
99                         
100                 if(graph.isInstanceOf(entry, DIA.Profile)) {
101                         Set<Resource> singleSelGroups = new HashSet<Resource>();
102                         
103                         for(Resource child : ProfileUtils.getProfileChildren(graph, entry)) {
104                                 if(checked && graph.isInstanceOf(child, DIA.ProfileEntry)) {
105                                         //enable only one item from single selection groups.
106                                         Resource group = graph.getPossibleObject(child, DIA.ProfileEntry_HasGroup);
107                                 if (group != null && graph.isInstanceOf(group, DIA.SingleSelectionGroup)) {
108                                         if (singleSelGroups.contains(group))
109                                                 continue;
110                                         singleSelGroups.add(group);
111                                 }
112                                 }
113                                 processRecursively(graph, runtimeDiagram, runtimeProfile, child, checked);
114                         }
115                         
116                 } else if(graph.isInstanceOf(entry, DIA.ProfileEntry)) {
117                         Resource group = graph.getPossibleObject(entry, DIA.ProfileEntry_HasGroup);
118                         if (group != null && graph.isInstanceOf(group, DIA.SingleSelectionGroup)) {
119                                  if(checked) {
120                                          //enable selected item from single selection groups, disable the rest.
121                                          Collection<Resource> entries = graph.getObjects(group, DIA.ProfileEntry_HasGroup_Inverse);
122                                          for (Resource e : entries) {
123                                                 deactivate(graph, runtimeDiagram, runtimeProfile, e);
124                                          }
125                                          activate(graph, runtimeDiagram, runtimeProfile, entry);
126                                  } else {
127                                          deactivate(graph, runtimeDiagram, runtimeProfile, entry);
128                                  }
129                         } else {
130                                     if(checked) {
131                                         activate(graph, runtimeDiagram, runtimeProfile, entry);
132                                     } else {
133                                         deactivate(graph, runtimeDiagram, runtimeProfile, entry);
134                                     }
135                         }
136
137                         }
138                         
139                 }
140
141                 private void activate(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry) throws DatabaseException {
142                         if(graph.isImmutable(runtimeProfile)) {
143                                 Resource activationState = ProfileUtils.claimProfileActivationState(graph, runtimeDiagram, runtimeProfile, entry);
144                                 if(activationState != null)
145                                         graph.claim(activationState, SimulationResource.getInstance(graph).IsActive, null, entry);
146                         } else {
147                                 graph.claim(runtimeProfile, SimulationResource.getInstance(graph).IsActive, null, entry);
148                         }
149                 }
150
151                 private void deactivate(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry) throws DatabaseException {
152                         if(graph.isImmutable(runtimeProfile)) {
153                                 Resource activationState = ProfileUtils.claimProfileActivationState(graph, runtimeDiagram, runtimeProfile, entry);
154                                 if(activationState != null)
155                             graph.denyStatement(activationState, SimulationResource.getInstance(graph).IsActive, entry);
156                         } else {
157                     graph.denyStatement(runtimeProfile, SimulationResource.getInstance(graph).IsActive, entry);
158                         }
159                 }
160                 
161             @Override
162             public Boolean apply(Object _event) {
163                 
164                 Event event = (Event)_event;
165                 
166                 if(event.detail == SWT.CHECK) {
167                         
168                     final TreeItem item = (TreeItem)event.item;
169                     Tree tree = item.getParent();
170                     GraphExplorer explorer = (GraphExplorer)tree.getData("GraphExplorer");
171                     final Resource runtimeDiagram = (Resource)explorer.getRoot().getConstant(BuiltinKeys.INPUT);
172                     final boolean checked = item.getChecked();
173                     NodeContext context = (NodeContext)item.getData();
174                     final ResourcePair entry = (ResourcePair)context.getConstant(BuiltinKeys.INPUT);
175                     try {
176                         
177                         VirtualGraphSupport support = Simantics.getSession().getService(VirtualGraphSupport.class);
178                         Simantics.getSession().syncRequest(new WriteRequest(support.getWorkspacePersistent("profiles")) {
179
180                             @Override
181                             public void perform(WriteGraph graph) throws DatabaseException {
182                                 
183                                 DiagramResource DIA = DiagramResource.getInstance(graph);
184                                 Resource runtimeProfile = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);
185                                 processRecursively(graph, runtimeDiagram, runtimeProfile, entry.getSecond(), checked);
186                                 
187                             }
188
189                         });
190                     } catch (DatabaseException e) {
191                         e.printStackTrace();
192                     }
193                 }
194                 
195                 return null;
196                 
197             }
198                 
199         };
200         
201     }
202     
203     @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
204     public static Object selectedProfile(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
205         
206         Resource runtimeDiagram = ScenegraphLoaderUtils.getResourceSelection(graph, context);
207         if(runtimeDiagram == null) return "";
208
209         Layer0 L0 = Layer0.getInstance(graph);
210         DiagramResource DIA = DiagramResource.getInstance(graph);
211         Resource profile = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);
212         if(profile == null) return null;
213         String name = graph.getPossibleRelatedValue(profile, L0.HasName, Bindings.STRING);
214         return StringUtils.safeString(name);
215
216     }
217
218     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
219     public static Object activeProfileModifier(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException {
220         
221         return new FunctionImpl1<String, String>() {
222
223                 @Override
224                 public String apply(final String key) {
225
226                         VirtualGraphSupport support = Simantics.getSession().getService(VirtualGraphSupport.class);
227                         Simantics.getSession().asyncRequest(new WriteRequest(support.getWorkspacePersistent("profiles")) {
228
229                                 public Resource selected(List<Tuple> avail, String text) {
230                                         for(Tuple a : avail) if(a.get(0).equals(text)) return (Resource)a.get(1);
231                                                         return null;
232                                 }
233
234                                 @Override
235                                 public void perform(WriteGraph graph) throws DatabaseException {
236
237                                         Resource runtimeDiagram = ScenegraphLoaderUtils.getResourceSelection(graph, context);
238
239                                         List<Tuple> avail = (List<Tuple>)availableProfiles(graph, resource, context);
240
241                                         final Resource profile = selected(avail, key);
242
243                                         DiagramResource DIA = DiagramResource.getInstance(graph);
244                                         Resource current = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);
245                                         if(profile.equals(current)) return;
246
247                                         graph.deny(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);
248                                         graph.claim(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile, null, profile);
249
250                                         // Set this profile as the default profile for this model
251                                         String modelURI = graph.getRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasModelURI);
252                                         Resource model = graph.getResource(modelURI);
253                                         graph.deny(model, DIA.HasActiveProfile);
254                                         graph.claim(model, DIA.HasActiveProfile, profile);
255
256                                         // Set this profile as the default profile for this diagram
257                                         Resource configuration = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);
258                                         graph.deny(configuration, DIA.HasActiveProfile);
259                                         graph.claim(configuration, DIA.HasActiveProfile, profile);
260
261                                 }
262
263                         });
264                         
265                         return null;
266
267                 }
268                 
269         };
270         
271     }
272
273     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource")
274     public static Resource singleResourceSelection(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
275         return ScenegraphLoaderUtils.getPossibleResourceSelection(graph, context);
276     }
277     
278 }