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