]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java
Merge commit '145a2884933f2ffdd48d6835729e58f1152d274e'
[simantics/platform.git] / bundles / org.simantics.spreadsheet.graph / src / org / simantics / spreadsheet / graph / GraphUI.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.spreadsheet.graph;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Collections;\r
17 import java.util.List;\r
18 import java.util.Map;\r
19 import java.util.function.Consumer;\r
20 \r
21 import org.eclipse.e4.core.contexts.IEclipseContext;\r
22 import org.eclipse.e4.ui.di.UISynchronize;\r
23 import org.eclipse.jface.dialogs.Dialog;\r
24 import org.eclipse.ui.PlatformUI;\r
25 import org.simantics.Simantics;\r
26 import org.simantics.databoard.Bindings;\r
27 import org.simantics.databoard.binding.Binding;\r
28 import org.simantics.databoard.binding.mutable.MutableVariant;\r
29 import org.simantics.databoard.binding.mutable.Variant;\r
30 import org.simantics.db.AsyncReadGraph;\r
31 import org.simantics.db.ReadGraph;\r
32 import org.simantics.db.RequestProcessor;\r
33 import org.simantics.db.Resource;\r
34 import org.simantics.db.WriteGraph;\r
35 import org.simantics.db.common.procedure.adapter.AsyncListenerSupport;\r
36 import org.simantics.db.common.procedure.adapter.ListenerSupport;\r
37 import org.simantics.db.common.procedure.adapter.SyncListenerSupport;\r
38 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
39 import org.simantics.db.common.procedure.single.SingleSetSyncListenerDelegate;\r
40 import org.simantics.db.common.request.ReadRequest;\r
41 import org.simantics.db.common.request.ResourceRead;\r
42 import org.simantics.db.common.request.UnaryRead;\r
43 import org.simantics.db.common.request.UniqueRead;\r
44 import org.simantics.db.common.request.WriteRequest;\r
45 import org.simantics.db.common.request.WriteResultRequest;\r
46 import org.simantics.db.common.session.SessionEventListenerAdapter;\r
47 import org.simantics.db.exception.DatabaseException;\r
48 import org.simantics.db.layer0.StandardRealm;\r
49 import org.simantics.db.layer0.request.PossibleURIVariable;\r
50 import org.simantics.db.layer0.request.VariableName;\r
51 import org.simantics.db.layer0.request.VariableRead;\r
52 import org.simantics.db.layer0.variable.ProxyVariables;\r
53 import org.simantics.db.layer0.variable.Variable;\r
54 import org.simantics.db.layer0.variable.Variables;\r
55 import org.simantics.db.procedure.SyncListener;\r
56 import org.simantics.db.request.Write;\r
57 import org.simantics.db.service.SessionEventSupport;\r
58 import org.simantics.layer0.Layer0;\r
59 import org.simantics.spreadsheet.Adaptable;\r
60 import org.simantics.spreadsheet.CellEditor;\r
61 import org.simantics.spreadsheet.ClientModel;\r
62 import org.simantics.spreadsheet.ClientModel.OperationMode;\r
63 import org.simantics.spreadsheet.SheetCommands;\r
64 import org.simantics.spreadsheet.event.model.RemoveCellHandler;\r
65 import org.simantics.spreadsheet.resource.SpreadsheetResource;\r
66 import org.simantics.ui.selection.WorkbenchSelectionUtils;\r
67 import org.simantics.utils.datastructures.Pair;\r
68 import org.simantics.utils.strings.AlphanumComparator;\r
69 import org.simantics.utils.threads.logger.ITask;\r
70 import org.simantics.utils.threads.logger.ThreadLogger;\r
71 import org.slf4j.Logger;\r
72 import org.slf4j.LoggerFactory;\r
73 \r
74 import gnu.trove.map.hash.THashMap;\r
75 import gnu.trove.map.hash.TObjectIntHashMap;\r
76 \r
77 class FilteredVariableProperties extends UnaryRead<Variable, Collection<Pair<String,Variable>>> {\r
78 \r
79         final static String CLASSIFICATION = SpreadsheetResource.URIs.Attribute;\r
80         \r
81     public FilteredVariableProperties(Variable variable) {\r
82         super(variable);\r
83     }\r
84 \r
85     @Override\r
86     public Collection<Pair<String,Variable>> perform(ReadGraph graph) throws DatabaseException {\r
87         ArrayList<Pair<String,Variable>> result = new ArrayList<Pair<String,Variable>>();\r
88         for(Variable var : parameter.getProperties(graph, CLASSIFICATION)) {\r
89                 String name = var.getName(graph);\r
90                 String uri = var.getURI(graph);\r
91                 result.add(Pair.make(name, var));\r
92                 Variable expression = var.getPossibleProperty(graph, "expression");\r
93                 if(expression != null)\r
94                     result.add(Pair.make(name + "#expression", expression));\r
95                 Variable editable = var.getPossibleProperty(graph, "editable");\r
96             if(editable != null)\r
97                 result.add(Pair.make(name + "#editable", editable));\r
98         }\r
99         return result;\r
100     }\r
101 \r
102 }\r
103 \r
104 public class GraphUI implements Adaptable, ListenerSupport, AsyncListenerSupport, SyncListenerSupport {\r
105 \r
106         private static final Logger LOGGER = LoggerFactory.getLogger(GraphUI.class);\r
107 \r
108         final public static boolean DEBUG = false;\r
109         \r
110     final private RequestProcessor processor;\r
111     \r
112     private CellEditor<Write> cellEditor;\r
113     \r
114     private Variable run;\r
115     private ClientModel client;\r
116 \r
117     private Map<String, PropertyListener> listenerCache = new THashMap<>();\r
118 \r
119     public GraphUI(RequestProcessor processor) {\r
120         this.processor = processor;\r
121     }\r
122     \r
123     public void addCell(ReadGraph graph, Pair<String, Variable> child, final ClientModel client) throws DatabaseException {\r
124 \r
125                 if(DEBUG) System.out.println("GraphUI adds cell  " + child.second.getURI(graph));\r
126 \r
127         final String childName = child.second.getName(graph);\r
128         Boolean immutable = child.second.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN);\r
129         if(immutable != null && immutable) {\r
130                 Collection<Variable> properties = child.second.getProperties(graph, FilteredVariableProperties.CLASSIFICATION);\r
131                 addProperties(graph, properties, client, childName);\r
132         } else {\r
133             PropertyListener listener = listenerCache.get(child.first); \r
134             if (listener == null) {\r
135                     listener = propertyListener(client, childName);\r
136                     listenerCache.put(child.first, listener);\r
137             }\r
138                 graph.asyncRequest(new FilteredVariableProperties(child.second), listener);\r
139         }\r
140 \r
141     }\r
142 \r
143     public void removeCell(ReadGraph graph, Pair<String, Variable> child, final ClientModel client) throws DatabaseException {\r
144 \r
145                 if(DEBUG) System.out.println("GraphUI removed cell " + child.first);\r
146                 \r
147                 client.clear(child.first);\r
148                 PropertyListener listener = listenerCache.remove(child.first);\r
149                 if (listener != null)\r
150                     listener.dispose();\r
151 \r
152     }\r
153 \r
154     public void loadCells(ReadGraph graph, Variable container, boolean immutable, final ClientModel client) throws DatabaseException {\r
155         \r
156                 if(DEBUG) System.out.println("GraphUI loads cells from " + container.getURI(graph));\r
157                 \r
158                 if(immutable) {\r
159                         for(Pair<String, Variable> cell : graph.syncRequest(new Cells(container), TransientCacheAsyncListener.<Collection<Pair<String, Variable>>>instance())) { \r
160                                 addCell(graph, cell, client);\r
161                         }\r
162                 } else {\r
163                 graph.syncRequest(new Cells(container), new SingleSetSyncListenerDelegate<Pair<String, Variable>>(GraphUI.this) {\r
164         \r
165                     @Override\r
166                     public void add(ReadGraph graph, final Pair<String, Variable> child) throws DatabaseException {\r
167                         addCell(graph, child, client);\r
168                     }\r
169         \r
170                     @Override\r
171                     public void remove(ReadGraph graph, final Pair<String, Variable> child) throws DatabaseException {\r
172                         removeCell(graph, child, client);\r
173                     }\r
174                 });\r
175                 }\r
176         \r
177     }\r
178     \r
179     private SessionEventListenerAdapter listener;\r
180     \r
181     private String currentSource;\r
182 \r
183     private boolean disposed;\r
184     \r
185     public Resource load(final Variable variable, final ClientModel client) throws DatabaseException {\r
186         \r
187 //        for (PropertyListener listener : listenerCache.values())\r
188 //            listener.dispose();\r
189 //        \r
190 //        listenerCache.clear();\r
191         \r
192         \r
193         \r
194         assert(variable != null);\r
195         \r
196         this.run = variable;\r
197         this.client = client;\r
198         \r
199         SessionEventSupport support = processor.getService(SessionEventSupport.class);\r
200         \r
201         for (PropertyListener listener : listenerCache.values()) {\r
202             listener.dispose();\r
203         }\r
204         listenerCache.clear();\r
205         \r
206         if(listener != null)\r
207                 support.removeListener(listener);\r
208         \r
209         listener = new SessionEventListenerAdapter() {\r
210                 \r
211                 @Override\r
212                 public void writeTransactionFinished() {\r
213                         client.flush();\r
214                 }\r
215                 \r
216         }; \r
217         \r
218         support.addListener(listener);\r
219 \r
220         this.cellEditor = processor.sync(new VariableRead<CellEditor<Write>>(variable) {\r
221 \r
222                         @Override\r
223                         public CellEditor<Write> perform(ReadGraph graph) throws DatabaseException {\r
224                                 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
225                                 return variable.getPropertyValue(graph, SHEET.cellEditor);\r
226                         }\r
227                 \r
228         });\r
229         \r
230                 final ITask task = ThreadLogger.getInstance().begin("GraphUI.init");\r
231 \r
232                 client.clearAll();\r
233 \r
234                 Map<String,Variable> sources = processor.syncRequest(new Sources(variable));\r
235 \r
236                 List<String> sheetList = processor.syncRequest(new Sheets(variable));\r
237                 String currentSheet = processor.syncRequest(new VariableName(variable));\r
238                 \r
239                 Map<String, Resource> stateList = processor.syncRequest(new SpreadsheetStates(variable));\r
240 \r
241                 if(currentSource == null) currentSource = "Sheet";\r
242                 \r
243                 ArrayList<String> sourceList = new ArrayList<String>(sources.keySet());\r
244                 \r
245                 Collections.sort(sourceList, AlphanumComparator.CASE_INSENSITIVE_COMPARATOR);\r
246                 if(!sourceList.contains(currentSource)) sourceList.add(currentSource);\r
247                 \r
248                 client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE, sourceList.toArray(new String[sourceList.size()]));\r
249                 client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, currentSource);\r
250 \r
251                 client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE, sheetList.toArray(new String[sheetList.size()]));\r
252                 client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, currentSheet);\r
253                 \r
254                 client.setProperty(ClientModel.STATES, ClientModel.STATES_AVAILABLE, stateList.keySet().toArray(new String[stateList.size()]));\r
255                 \r
256                 client.setProperty(ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, variable);\r
257                 \r
258                 client.setProperty(ClientModel.MODE, ClientModel.MODE_CURRENT, OperationMode.OPERATION);\r
259                 \r
260                 String currentState = processor.syncRequest(new UniqueRead<String>() {\r
261 \r
262             @Override\r
263             public String perform(ReadGraph graph) throws DatabaseException {\r
264                 Resource book = variable.getParent(graph).getRepresents(graph);\r
265                 Resource ic = graph.getPossibleObject(book, SpreadsheetResource.getInstance(graph).Book_HasDefaultInitialCondition);\r
266                 if (ic == null)\r
267                         return "";\r
268                 return graph.getRelatedValue2(ic, Layer0.getInstance(graph).HasName, Bindings.STRING);\r
269             }\r
270         });\r
271                 \r
272                 client.setProperty(ClientModel.STATES, ClientModel.STATES_CURRENT, currentState);\r
273 \r
274         processor.syncRequest(new ReadRequest() {\r
275 \r
276             @Override\r
277             public void run(ReadGraph graph) throws DatabaseException {\r
278 \r
279                 loadCells(graph, variable, false, client);\r
280 \r
281                 graph.syncRequest(new Ranges(variable), new SingleSetSyncListenerDelegate<Variable>(GraphUI.this) {\r
282 \r
283                     @Override\r
284                     public void add(ReadGraph graph, final Variable range) throws DatabaseException {\r
285 \r
286                                 if(DEBUG) System.out.println("GraphUI adds range  " + range.getURI(graph));\r
287 \r
288                         Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN);\r
289                         loadCells(graph, range, immutable != null && immutable, client);\r
290 \r
291                     }\r
292 \r
293                     @Override\r
294                     public void remove(ReadGraph graph, final Variable range) throws DatabaseException {\r
295 \r
296                     }\r
297                     \r
298                 });\r
299                 \r
300                 \r
301                 graph.syncRequest(new SheetLines(variable), new SingleSetSyncListenerDelegate<Variable>(GraphUI.this) {\r
302 \r
303                     @Override\r
304                     public void add(ReadGraph graph, final Variable range) throws DatabaseException {\r
305 \r
306                                 if(DEBUG) System.out.println("GraphUI adds line  " + range.getURI(graph));\r
307 \r
308                         Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN);\r
309                         loadCells(graph, range, immutable != null && immutable, client);\r
310 \r
311                     }\r
312 \r
313                     @Override\r
314                     public void remove(ReadGraph graph, final Variable range) throws DatabaseException {\r
315 \r
316                     }\r
317                 });\r
318 \r
319             }\r
320 \r
321 //            @Override\r
322 //            public void remove(ReadGraph graph, Variable child) throws DatabaseException {\r
323 //\r
324 //              String location = locations.get(cellResource);\r
325 //              assert(location != null);\r
326 //\r
327 //              client.setProperty(location, "Label", null);\r
328 //              client.setProperty(location, "Expression", null);\r
329 //\r
330 //            }\r
331 \r
332         });\r
333         \r
334 \r
335                 task.finish();\r
336                 client.flush();\r
337                 \r
338                 return null;\r
339 \r
340     }\r
341     \r
342     private static class PropertyListener extends SingleSetSyncListenerDelegate<Pair<String,Variable>> {\r
343 \r
344         private static final Logger LOGGER = LoggerFactory.getLogger(PropertyListener.class);\r
345 \r
346         private ClientModel client;\r
347         private String childName;\r
348         private boolean listenerDisposed;\r
349 \r
350         public PropertyListener(AsyncListenerSupport support, ClientModel client, String childName) {\r
351             super(support);\r
352             this.client = client;\r
353             this.childName = childName;\r
354         }\r
355         \r
356         @Override\r
357         public void add(ReadGraph graph, final Pair<String,Variable> property) throws DatabaseException {\r
358 \r
359             if(DEBUG)\r
360                 System.out.println("GraphUI adds property  " + property.second.getURI(graph));\r
361 \r
362             graph.asyncRequest(new CellValue(property.second), new SyncListener<Object>() {\r
363 \r
364                 @Override\r
365                 public void execute(ReadGraph graph, final Object value) throws DatabaseException {\r
366 \r
367                     String propertyName = property.first;\r
368 \r
369                     if(DEBUG)\r
370                         System.out.println("GraphUI detected content change(1) at  " + childName + " - " + propertyName + " -> " + value);\r
371                     client.setProperty(childName, propertyName, value);\r
372                     \r
373                 }\r
374 \r
375                 @Override\r
376                 public void exception(ReadGraph graph, Throwable throwable) throws DatabaseException {\r
377                     \r
378                     LOGGER.error("PropertyListener.exception", throwable);\r
379                     \r
380                     String propertyName = property.first;\r
381                     if("content".equals(propertyName)) {\r
382                         if(throwable == null) throwable = new Exception();\r
383                         String message = throwable.getMessage();\r
384                         if(message == null) message = throwable.toString();\r
385                         client.setProperty(childName, propertyName, Variant.ofInstance(message));\r
386                     } else {\r
387                         client.setProperty(childName, propertyName, null);\r
388                     }\r
389                     \r
390                 }\r
391 \r
392                 @Override\r
393                 public boolean isDisposed() {\r
394                     return listenerDisposed;\r
395                 }\r
396 \r
397             });\r
398         }\r
399 \r
400         public void dispose() {\r
401             listenerDisposed = true;\r
402         }\r
403         \r
404         @Override\r
405         public String toString() {\r
406             return super.toString() + ":" + childName;\r
407         }\r
408         \r
409     }\r
410     \r
411     private PropertyListener propertyListener(final ClientModel client, final String childName) {\r
412         return new PropertyListener(this, client, childName);\r
413     }\r
414     \r
415     private void addProperties(ReadGraph graph, final Collection<Variable> properties, final ClientModel client, final String childName) throws DatabaseException {\r
416 \r
417         for(Variable property : properties) {\r
418                 \r
419                 if(DEBUG) System.out.println("GraphUI adds immutable property  " + property.getURI(graph));\r
420 \r
421                 final String propertyName = property.getName(graph);\r
422                 \r
423                 Object value = property.getValue(graph);\r
424 \r
425                 if(DEBUG) System.out.println("GraphUI detected change at  " + childName + " - " + propertyName + " -> " + value);\r
426                 client.setProperty(childName, propertyName, value);\r
427                 \r
428                 String expression = property.getPossiblePropertyValue(graph, "expression", Bindings.STRING);\r
429                 if(expression != null) {\r
430                         if(DEBUG) System.out.println("GraphUI detected change at  " + childName + " - " + (propertyName + "#expression") + " -> " + value);\r
431                         client.setProperty(childName, propertyName + "#expression", expression);\r
432                 }\r
433                 \r
434             Boolean editable = property.getPossiblePropertyValue(graph, "editable", Bindings.STRING);\r
435             if(editable != null) {\r
436                 if(DEBUG) System.out.println("GraphUI detected change at  " + childName + " - " + (propertyName + "#editable") + " -> " + value);\r
437                 client.setProperty(childName, propertyName + "#editable", editable);\r
438             }\r
439         \r
440         }\r
441 \r
442     }\r
443     \r
444     @SuppressWarnings("unchecked")\r
445     @Override\r
446     public <T> T getAdapter(Class<T> clazz) {\r
447 \r
448         if(Variable.class == clazz) {\r
449 \r
450                 return (T)run;\r
451                 \r
452         } else if(RemoveCellHandler.class == clazz) {\r
453                 \r
454             return (T) new RemoveCellHandler() {\r
455 \r
456                                 @Override\r
457                                 public void handle(final String location) {\r
458                                         \r
459                                 processor.asyncRequest(new ReadRequest() {\r
460 \r
461                                     @Override\r
462                                     public void run(ReadGraph graph) throws DatabaseException {\r
463                                         \r
464                                                         Variable cellVariable = run.getPossibleChild(graph, location);\r
465                                                         if(cellVariable != null) {\r
466                                                                 final Resource config = cellVariable.getPossiblePropertyValue(graph, "Represents");\r
467                                                                 if(config != null) {\r
468                                                                         \r
469                                                                         graph.asyncRequest(new WriteRequest() {\r
470 \r
471                                                                                 @Override\r
472                                                                                 public void perform(WriteGraph graph) throws DatabaseException {\r
473                                                                                         \r
474                                                                                         Layer0 l0 = Layer0.getInstance(graph);\r
475 //                                                                                      SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);\r
476                                                                                         graph.deny(config, l0.PartOf);\r
477 //                                                                                      graph.deny(config, sr.RowOf);\r
478 //                                                                                      graph.deny(config, sr.ColumnOf);\r
479                                                                                         \r
480                                                                                 }\r
481                                                                                 \r
482                                                                         });\r
483                                                                         \r
484                                                                 }\r
485                                                         }\r
486                                                         \r
487                                     }\r
488                                     \r
489                                 });\r
490                                         \r
491                                 }\r
492                 \r
493             };\r
494 \r
495         } else if(CellEditor.class == clazz) {\r
496         \r
497                 return (T)new CellEditor<Write>() {\r
498 \r
499                                 @Override\r
500                                 public <E> void edit(Transaction<Write> transaction, String location, String property, E value, Binding binding, Consumer<?> callback) {\r
501                                         \r
502                                     if (ClientModel.ITERATION_ENABLED.equals(location)) {\r
503                                         Simantics.getSession().asyncRequest(new ReadRequest() {\r
504                                                         @Override\r
505                                                         public void run(ReadGraph graph) throws DatabaseException {\r
506                                                                 getBook(graph).setIterationEnabled((boolean)value);\r
507                                                         }\r
508                                                 });\r
509                                         return;\r
510                                     }\r
511                                     \r
512                                     if (ClientModel.MODE.equals(location)) {\r
513                                         if (ClientModel.MODE_CURRENT.equals(property)) {\r
514                                             client.setProperty(location, property, value);\r
515                                             client.flush();\r
516                                             return;\r
517                                         }\r
518                                     }\r
519                                     \r
520                                     if (ClientModel.CONTEXT.equals(location)) {\r
521                                         if(ClientModel.CONTEXT_CURRENT.equals(property)) {\r
522                             if(value instanceof String) {\r
523                                 try {\r
524                                     Variable newContext = processor.syncRequest(new UnaryRead<String, Variable>((String)value) {\r
525 \r
526                                         @Override\r
527                                         public Variable perform(ReadGraph graph) throws DatabaseException {\r
528                                       \r
529                                             String sheetName = run.getName(graph);\r
530                                             \r
531                                             Variable book = Variables.getContext(graph, run);\r
532                                             Resource bookResource = book.getRepresents(graph);\r
533                                             \r
534                                             Variable input = Variables.getVariable(graph, parameter);\r
535                                             Variable proxy = ProxyVariables.makeProxyVariable(graph, Variables.getVariable(graph, bookResource), input);\r
536                                             \r
537                                             return proxy.getChild(graph, sheetName);\r
538                                             \r
539 //                                            return variable.getParent(graph).getChild(graph, parameter);\r
540                                         }\r
541 \r
542                                     });\r
543                                     \r
544                                     load(newContext, client);\r
545                                     return;\r
546                                 } catch (DatabaseException e) {\r
547                                     LOGGER.error("edit failed for model key '" + ClientModel.CONTEXT_CURRENT + "'", e);\r
548                                 }\r
549                             }\r
550                                         }\r
551                                     }\r
552                                     \r
553                                         if(ClientModel.SHEETS.equals(location)) {\r
554                                                 if(ClientModel.SHEETS_CURRENT.equals(property)) {\r
555                                                         \r
556                                                         if(value instanceof String) {\r
557 \r
558                                                                 try {\r
559 \r
560                                                                         Variable newInput = processor.syncRequest(new UnaryRead<String, Variable>((String)value) {\r
561 \r
562                                                                                 @Override\r
563                                                                                 public Variable perform(ReadGraph graph) throws DatabaseException {\r
564                                                                                         return run.getParent(graph).getChild(graph, parameter);\r
565                                                                                 }\r
566 \r
567                                                                         });\r
568 \r
569                                                                         load(newInput, client);\r
570                                                                         return;\r
571                                                                 } catch (DatabaseException e) {\r
572                                                                         LOGGER.error("edit failed for model key '" + ClientModel.SHEETS_CURRENT + "'", e);\r
573                                                                 }\r
574                                                         }\r
575                                                 }\r
576                                         }\r
577                                         \r
578                    if(ClientModel.STATES.equals(location)) {\r
579                         if(ClientModel.STATES_CURRENT.equals(property)) {\r
580                             if(value instanceof String) {\r
581                                 final String parameter = (String) value;\r
582                                 try {\r
583                                     \r
584                                     String uri = processor.syncRequest(new WriteResultRequest<String>() {\r
585                 \r
586                                         @Override\r
587                                         public String perform(WriteGraph graph) throws DatabaseException {\r
588                                             \r
589                                             Map<String, Resource> states = graph.syncRequest(new SpreadsheetStates(run));\r
590                                             \r
591                                             Resource state = null;\r
592                                             for (Map.Entry<String, Resource> entry : states.entrySet()) {\r
593                                                 if (entry.getKey().equals(parameter)) {\r
594                                                     state = entry.getValue();\r
595                                                     break;\r
596                                                 }\r
597                                             }\r
598                                             if (state != null) {\r
599                                                 Variable context = Variables.getContext(graph, run);\r
600                                                 Resource bookResource = context.getRepresents(graph);\r
601                                                 SpreadsheetGraphUtils.setDefaultInitialConditionForBook(graph, bookResource, state);\r
602                                                 \r
603                                                 String contextURI = context.getURI(graph);\r
604                                                 \r
605                                                 String sessionName = context.getParent(graph).getURI(graph);\r
606                                                 SpreadsheetSessionManager.getInstance().removeRealm(sessionName);\r
607                                                 SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);\r
608                                             }\r
609                                             \r
610                                             return run.getURI(graph);\r
611                                         }\r
612                                     });\r
613                                     Variable newInput = processor.syncRequest(new PossibleURIVariable(uri));\r
614                                     load(newInput, client);\r
615 //                                    fullSynchronize();\r
616                                     return;\r
617                                 } catch (DatabaseException e) {\r
618                                     LOGGER.error("edit failed for model key '" + ClientModel.STATES_CURRENT + "'", e);\r
619                                 }\r
620                             }\r
621                         }\r
622                     }\r
623 \r
624                                         if(ClientModel.SOURCES.equals(location)) {\r
625                                                 if(ClientModel.SOURCES_CURRENT.equals(property)) {\r
626                                                         try {\r
627                                                                 Resource res = WorkbenchSelectionUtils.getPossibleResource(value);\r
628                                                                 if(res != null) {\r
629                                                                         \r
630                                                                         Variable newInput = processor.syncRequest(new ResourceRead<Variable>(res) {\r
631 \r
632                                                                                 @Override\r
633                                                                                 public Variable perform(ReadGraph graph) throws DatabaseException {\r
634                                                                                         Variable base = ProxyVariables.proxyVariableBase(graph, run);\r
635                                                                                         Variable in = Variables.getVariable(graph, resource);\r
636                                                                                         currentSource = in.getURI(graph);\r
637                                                                                         return ProxyVariables.makeProxyVariable(graph, base, in);\r
638                                                                                 }\r
639                                                 \r
640                                                                         });\r
641                                                                         \r
642                                                                         load(newInput, client);\r
643                                                                         \r
644                                                                         return;\r
645 \r
646                                                                 } else if(value instanceof String) {\r
647                                                                         \r
648                                                                         Variable newInput = processor.syncRequest(new UnaryRead<String, Variable>((String)value) {\r
649 \r
650                                                                                 @Override\r
651                                                                                 public Variable perform(ReadGraph graph) throws DatabaseException {\r
652                                                                                         \r
653                                                                                         Variable base = ProxyVariables.proxyVariableBase(graph, run);\r
654                                                                                         Map<String,Variable> sources = graph.syncRequest(new Sources(base));\r
655 \r
656                                                                                         Variable found = sources.get(parameter);\r
657                                                                                         if(found == null) return null;\r
658                                                                                         \r
659                                                                                         currentSource = parameter;\r
660 \r
661                                                                                         return ProxyVariables.makeProxyVariable(graph, base, found);\r
662                                                                                         \r
663                                                                                 }\r
664                                                 \r
665                                                                         });\r
666                                                                         \r
667                                                                         load(newInput, client);\r
668                                                                         return;\r
669                                                                 }\r
670                                                                 \r
671                                                         } catch (DatabaseException e) {\r
672                                                                 LOGGER.error("edit failed for model key '" + ClientModel.SOURCES_CURRENT + "'", e);\r
673                                                         }\r
674                                                 }\r
675                                                 return;\r
676                                         }\r
677                                         boolean needsCommit = false;\r
678                                         if (transaction == null) {\r
679                                             OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
680                                             transaction = startTransaction(mode);\r
681 //                                          if (mode.equals(OperationMode.OPERATION))\r
682                                         transaction.setContext(run);\r
683                                             needsCommit = true;\r
684                                         }\r
685                                         final Transaction<Write> finalTransaction = transaction;\r
686                                         cellEditor.edit(transaction, location, property, value, binding, new Consumer<Object>() {\r
687                         \r
688                         @Override\r
689                         public void accept(Object param) {\r
690                             if (finalTransaction.needSynchronization() != null)\r
691                                 synchronize(finalTransaction.needSynchronization());\r
692                         }\r
693                                         });\r
694                                         if (needsCommit)\r
695                                             transaction.commit();\r
696                                 }\r
697 \r
698                                 @Override\r
699                                 public void edit(Transaction<Write> transaction, String location, Variant variant, Consumer<?> callback) {\r
700                                     boolean needsCommit = false;\r
701                                     if (transaction == null) {\r
702                                         OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT);\r
703                                         transaction = startTransaction(mode);\r
704 //                                      if (mode.equals(OperationMode.OPERATION))\r
705                                     transaction.setContext(run);\r
706                                         needsCommit = true;\r
707                                     }\r
708                                     final Transaction<Write> finalTransaction = transaction;\r
709                                         cellEditor.edit(transaction, location, variant, new Consumer<Object>() {\r
710                         \r
711                         @Override\r
712                         public void accept(Object param) {\r
713                             if (finalTransaction.needSynchronization() != null)\r
714                                 synchronize(finalTransaction.needSynchronization());\r
715                         }\r
716                     });\r
717                                         if (needsCommit)\r
718                                             transaction.commit();\r
719                                 }\r
720 \r
721                                 @Override\r
722                                 public void copy(final Transaction<Write> transaction, String location, MutableVariant variant, Consumer<?> callback) {\r
723                                         cellEditor.edit(transaction, location, variant, new Consumer<Object>() {\r
724                         \r
725                         @Override\r
726                         public void accept(Object param) {\r
727                             if (transaction.needSynchronization() != null)\r
728                                 synchronize(transaction.needSynchronization());\r
729                         }\r
730                                         });\r
731                                 }\r
732 \r
733                                 @Override\r
734                                 public Transaction<Write> startTransaction(OperationMode mode) {\r
735                                         return cellEditor.startTransaction(mode);\r
736                                 }\r
737                                 \r
738                 };\r
739                 \r
740         } else if (SheetCommands.class == clazz ) {\r
741             \r
742             return (T) new SheetCommands() {\r
743                 \r
744                 @Override\r
745                 public void saveState() {\r
746                     \r
747                     Simantics.getSession().asyncRequest(new ReadRequest() {\r
748                         \r
749                         @Override\r
750                         public void run(ReadGraph graph) throws DatabaseException {\r
751                             IEclipseContext context = PlatformUI.getWorkbench().getService(IEclipseContext.class);\r
752                             \r
753                             Resource uiContextResource = run.getRepresents(graph);\r
754                             Resource bookResource = Variables.getContext(graph, run).getRepresents(graph);\r
755                             Layer0 L0 = Layer0.getInstance(graph);\r
756                             String uiContextName = graph.getRelatedValue2(uiContextResource, L0.HasName, Bindings.STRING);\r
757                             String bookName = graph.getRelatedValue2(bookResource, L0.HasName, Bindings.STRING);\r
758                             \r
759                             UISynchronize synchronizer = context.get(UISynchronize.class);\r
760                             synchronizer.asyncExec(() -> {\r
761                                 Pair<String, Resource>[] pairs = new Pair[] {Pair.make(uiContextName, uiContextResource), Pair.make(bookName, bookResource) };\r
762                                 SaveSpreadsheetStateDialog dialog = new SaveSpreadsheetStateDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getSite(), "Save Spreadsheet state", pairs);\r
763                                 if (dialog.open() == Dialog.OK) {\r
764                                     Object[] result = dialog.getSelection();\r
765                                     if (result != null) {\r
766                                         Pair<Resource, String> p = (Pair<Resource, String>) result[0];\r
767                                         Simantics.getSession().asyncRequest(new WriteRequest() {\r
768                                             \r
769                                             @Override\r
770                                             public void perform(WriteGraph graph) throws DatabaseException {\r
771                                                 \r
772                                                 Variable parent = run.getParent(graph);\r
773                                                 Variable base = ProxyVariables.proxyVariableBase(graph, parent);\r
774                                                 SpreadsheetGraphUtils.saveInitialCondition(graph, parent, p.first, p.second);\r
775                                             }\r
776                                         });\r
777                                     }\r
778                                 } else {\r
779                                     return;\r
780                                 }\r
781                             });\r
782                         }\r
783                     });\r
784                 }\r
785             };\r
786         }\r
787 \r
788         return null;\r
789 \r
790     }\r
791 \r
792     @Override\r
793     public void exception(Throwable t) {\r
794         t.printStackTrace();\r
795     }\r
796 \r
797     @Override\r
798     public boolean isDisposed() {\r
799         return disposed;\r
800     }\r
801 \r
802     @Override\r
803     public void exception(AsyncReadGraph graph, Throwable t) {\r
804         LOGGER.error("Failed to read properties.", t);\r
805     }\r
806 \r
807     @Override\r
808     public void exception(ReadGraph graph, Throwable t) {\r
809         LOGGER.error("Failed to read properties.", t);\r
810     }\r
811 \r
812     public void dispose() {\r
813         for (PropertyListener listener : listenerCache.values())\r
814             listener.dispose();\r
815         \r
816         listenerCache.clear();\r
817         SessionEventSupport support = processor.getService(SessionEventSupport.class);\r
818         support.removeListener(listener);\r
819         disposed = true;\r
820     }\r
821     \r
822     private void synchronize(List<Object> list) {\r
823         Simantics.getSession().asyncRequest(new FullSynchronizeBook(run, list));\r
824     }\r
825     \r
826     public static class FullSynchronizeBook extends ReadRequest {\r
827 \r
828         private final Variable run;\r
829         private final List<Object> location;\r
830         \r
831         public FullSynchronizeBook(Variable run, List<Object> cellLocation) {\r
832             this.run = run;\r
833             this.location = cellLocation;\r
834         }\r
835         \r
836         @Override\r
837         public void run(ReadGraph graph) throws DatabaseException {\r
838             String uri = run.getURI(graph);\r
839             String parentUri = run.getParent(graph).getURI(graph);\r
840             System.err.println("Full sync for book " + parentUri);\r
841             \r
842             Resource sheetResource = run.getRepresents(graph);\r
843             Variable sheetVariable = Variables.getVariable(graph, sheetResource);\r
844             \r
845             TObjectIntHashMap<Variable> changes = null;\r
846             if (location != null) {\r
847                 changes = new TObjectIntHashMap<>(location.size());\r
848                 for (Object loc : location) {\r
849                     Variable var = (Variable) loc;\r
850                     changes.put(var, 1);\r
851                 };\r
852             }\r
853             SpreadsheetGraphUtils.partialSynchronization(graph, run.getParent(graph), changes);\r
854         }\r
855         \r
856     }\r
857     \r
858     private SpreadsheetBook getBook(ReadGraph graph) throws DatabaseException {\r
859         String sessionName = run.getParent(graph).getParent(graph).getURI(graph);\r
860         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);\r
861         SpreadsheetBook book = realm.getEngine();\r
862         return book;\r
863     }\r
864     \r
865 }\r