47e866d0f61a651d7df83d53c93e6041740cdd09
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / selection / WorkbenchSelectionUtils.java
1 package org.simantics.ui.selection;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.stream.Collectors;
9
10 import org.eclipse.core.commands.ExecutionEvent;
11 import org.eclipse.jface.viewers.ISelection;
12 import org.eclipse.ui.handlers.HandlerUtil;
13 import org.simantics.Simantics;
14 import org.simantics.db.ReadGraph;
15 import org.simantics.db.RequestProcessor;
16 import org.simantics.db.Resource;
17 import org.simantics.db.common.primitiverequest.IsInstanceOf;
18 import org.simantics.db.common.primitiverequest.Supertypes;
19 import org.simantics.db.common.primitiverequest.Types;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.layer0.request.PossibleURI;
22 import org.simantics.db.layer0.request.PossibleVariableRepresents;
23 import org.simantics.db.layer0.request.VariableRead;
24 import org.simantics.db.layer0.request.VariableURI;
25 import org.simantics.db.layer0.variable.Variable;
26 import org.simantics.utils.ui.ISelectionUtils;
27
28 public class WorkbenchSelectionUtils {
29
30         public static Resource getPossibleResource(ExecutionEvent event) throws DatabaseException {
31                 ISelection selection = HandlerUtil.getCurrentSelection(event);
32                 return getPossibleResource(selection);
33         }
34         
35         public static Variable getPossibleVariable(ExecutionEvent event) throws DatabaseException {
36                 ISelection selection = HandlerUtil.getCurrentSelection(event);
37                 return getPossibleVariable(selection);
38         }
39         
40         public static List<WorkbenchSelectionElement> getWorkbenchSelectionElements(ISelection selection) {
41             return ISelectionUtils.filterSelection(selection, WorkbenchSelectionElement.class);
42         }
43
44         public static String getPossibleJSON(Object selection) throws DatabaseException {
45                 WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection);
46                 return element != null ? getPossibleJSON(element) : null;
47         }
48
49         public static Resource getPossibleResource(Object selection) throws DatabaseException {
50                 WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection);
51                 return element != null ? getPossibleResource(element) : null;
52         }
53
54         public static Variable getPossibleVariable(Object selection) throws DatabaseException {
55                 WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection);
56                 return element != null ? getPossibleVariable(element) : null;
57         }
58
59         public static Resource getPossibleResourceFromSelection(RequestProcessor processor, Object selection) throws DatabaseException {
60                 WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection);
61                 return element != null ? getPossibleResource(processor, element) : null;
62         }
63
64         public static Variable getPossibleVariableFromSelection(RequestProcessor processor, Object selection) throws DatabaseException {
65                 WorkbenchSelectionElement element = getPossibleWorkbenchSelectionElement(selection);
66                 return element != null ? getPossibleVariable(processor, element) : null;
67         }
68
69         public static Variable getPossibleVariable(Object[] selection) throws DatabaseException {
70                 if(selection.length != 1) return null;
71                 if(!(selection[0] instanceof WorkbenchSelectionElement)) return null;
72                 return getPossibleVariable((WorkbenchSelectionElement)selection[0]);
73         }
74
75         public static <T> T getPossibleElement(Object[] selection, WorkbenchSelectionContentType<T> contentType) throws DatabaseException {
76                 if(selection.length != 1) return null;
77                 if(!(selection[0] instanceof WorkbenchSelectionElement)) return null;
78                 WorkbenchSelectionElement wse = (WorkbenchSelectionElement)selection[0];
79                 return wse.getContent(contentType);
80         }
81
82         public static String getPossibleJSON(WorkbenchSelectionElement wse) throws DatabaseException {
83                 return getPossibleJSON(Simantics.getSession(), wse);
84         }
85
86         public static Resource getPossibleResource(WorkbenchSelectionElement wse) throws DatabaseException {
87                 return getPossibleResource(Simantics.getSession(), wse);
88         }
89
90         public static Variable getPossibleVariable(WorkbenchSelectionElement wse) throws DatabaseException {
91                 return getPossibleVariable(Simantics.getSession(), wse);
92         }
93
94         public static Variable getPossibleVariableSCL(ReadGraph graph, WorkbenchSelectionElement wse) throws DatabaseException {
95                 return getPossibleVariable(graph, wse);
96         }
97
98         public static Resource getPossibleResourceSCL(ReadGraph graph, WorkbenchSelectionElement wse) throws DatabaseException {
99                 return getPossibleResource(graph, wse);
100         }
101
102         public static String getPossibleJSON(RequestProcessor processor, Object input) throws DatabaseException {
103                 Variable var = getPossibleVariable(processor, input);
104                 Resource res = getPossibleResource(processor, input);
105                 String typesStr = getTypeResourceString(processor, res, var);
106                 if(var != null) {
107                         String uri = processor.syncRequest(new VariableURI(var));
108                         return toJSONObjectString(
109                                         "type", "\"Variable\"",
110                                         "uri", safeQuotedString(uri),
111                                         "typeResources", typesStr);
112                 }
113                 if(res != null) {
114                         String uri = processor.syncRequest(new PossibleURI(res));
115                         return toJSONObjectString(
116                                         "type", "\"Resource\"",
117                                         "uri", safeQuotedString(uri),
118                                         "typeResources", typesStr);
119                 }
120                 return "{ \"type\": \"Unknown\" }";
121         }
122
123         public static Resource getPossibleResource(RequestProcessor processor, Object input) throws DatabaseException {
124                 return getPossibleResource(processor, input, null);
125         }
126
127         public static Resource getPossibleResource(RequestProcessor processor, Object input, Resource type) throws DatabaseException {
128             if(input instanceof Collection && !((Collection<?>)input).isEmpty()) {
129                 Object element = ((Collection<?>)input).iterator().next();
130                 if(element instanceof Resource)
131                     return (Resource)element;
132             }
133                 Resource resource = getPossibleElement(input, new AnyResource(processor));
134                 if(resource == null) return resource;
135                 if(type != null) {
136                         if(processor.sync(new IsInstanceOf(resource, type))) return resource;
137                         else return null;
138                 }
139                 return resource;
140         }
141
142         public static Variable getPossibleVariable(RequestProcessor processor, Object input) throws DatabaseException {
143                 return getPossibleElement(input, new AnyVariable(processor));
144         }
145
146         public static <T> T getPossibleElement(Object input, WorkbenchSelectionContentType<T> contentType) {
147                 Object single = getPossibleSingleElement(input);
148                 if(single == null) return null;
149                 if(single instanceof WorkbenchSelectionElement) {
150                         WorkbenchSelectionElement element = (WorkbenchSelectionElement)single;
151                         return (T)element.getContent(contentType);
152                 }
153                 return null;
154         }
155         
156         public static WorkbenchSelectionElement getPossibleSelectionElement(Object input) {
157         if(input instanceof WorkbenchSelectionElement) return (WorkbenchSelectionElement)input;
158         if(input instanceof Collection) {
159                 Collection<?> c = (Collection<?>)input;
160                 if(c.size() == 1) {
161                         Object o = c.iterator().next();
162                         if(o instanceof WorkbenchSelectionElement) return (WorkbenchSelectionElement)o;
163                 }
164         }
165         return null;
166         }
167
168         // Internal helpers
169         
170     private static Object getPossibleSingleElement(Object input) {
171         if(input instanceof WorkbenchSelectionElement) return input;
172         if(input instanceof Collection) {
173                 Collection<?> c = (Collection<?>)input;
174                 if(c.size() == 1) return c.iterator().next();
175         } 
176         return null;
177     }   
178
179     private static WorkbenchSelectionElement getPossibleWorkbenchSelectionElement(Object selection) {
180         return getPossibleObject(selection, WorkbenchSelectionElement.class);
181     }
182
183     @SuppressWarnings("unchecked")
184     private static <T> T getPossibleObject(Object selection, Class<T> clazz) {
185         return clazz.isInstance(selection)
186                 ? (T) selection
187                 : ISelectionUtils.filterSingleSelection(selection, clazz);
188     }
189
190     private static class PossibleVariableType extends VariableRead<Resource> {
191
192         public PossibleVariableType(Variable var) {
193             super(var);
194         }
195
196         @Override
197         public Resource perform(ReadGraph graph) throws DatabaseException {
198             return variable.getPossibleType(graph);
199         }
200
201     }
202
203         private static String toJSONObjectString(String... keyValuePairs) {
204                 int len = keyValuePairs.length;
205                 assert (len & 1) == 0;
206                 StringBuilder sb = new StringBuilder(128);
207                 sb.append("{ ");
208                 int entryCount = 0;
209                 for (int i = 0; i < len; i += 2) {
210                         String value = keyValuePairs[i+1];
211                         if (value != null && !value.isEmpty()) {
212                                 if (entryCount > 0)
213                                         sb.append(", ");
214                                 sb.append("\"").append(keyValuePairs[i]).append("\": ").append(value);
215                                 ++entryCount;
216                         }
217                 }
218                 sb.append(" }");
219                 return sb.toString();
220         }
221
222         private static String escapeQuotes(String s) {
223                 return s.indexOf('"') >= 0 ? s.replaceAll("\"", "\\\\\"") : s;
224         }
225
226         private static String safeQuotedString(String s) {
227                 return s != null && !s.isEmpty() ? "\"" + escapeQuotes(s) + "\"" : "";
228         }
229
230         private static String toJSONStringArray(List<String> strings) throws DatabaseException {
231                 // Sort the type strings to produce stable results
232                 if (strings.isEmpty())
233                         return "";
234                 return strings.stream()
235                                 .map(WorkbenchSelectionUtils::escapeQuotes)
236                                 .sorted()
237                                 .collect(Collectors.joining("\", \"", "[\"", "\"]"));
238         }
239
240         private static String getTypeResourceString(RequestProcessor processor, Resource r, Variable v) throws DatabaseException {
241                 return toJSONStringArray(
242                                 toPossibleURIs(processor,
243                                                 getTypes(processor, r, v)));
244         }
245
246         private static Set<Resource> getTypes(RequestProcessor processor, Resource r, Variable v) throws DatabaseException {
247                 if (r == null && v != null)
248                         r = processor.syncRequest(new PossibleVariableRepresents(v));
249                 if (r != null)
250                         return processor.syncRequest(new Types(r));
251                 r = v != null ? processor.syncRequest(new PossibleVariableType(v)) : null;
252                 return r != null ? processor.syncRequest(new Supertypes(r)) : Collections.emptySet();
253         }
254
255         private static List<String> toPossibleURIs(RequestProcessor processor, Collection<Resource> resources) throws DatabaseException {
256                 if (resources.isEmpty())
257                         return Collections.emptyList();
258                 List<String> result = new ArrayList<>(resources.size());
259                 for (Resource r : resources) {
260                         String uri = processor.syncRequest(new PossibleURI(r));
261                         if (uri != null)
262                                 result.add(uri);
263                 }
264                 return result;
265         }
266
267 }