X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.spreadsheet.graph%2Fsrc%2Forg%2Fsimantics%2Fspreadsheet%2Fgraph%2FGraphUI.java;h=5850eb84750d7303e64a33abac540fc850c7e4ab;hp=b2fc404f23f200b1ff3477ce24e45c8bd22652e0;hb=82ed7c74dbd83a2a557e781b8674b3262b52da54;hpb=901596bae43d738281c8f02b4b27348c1964be51 diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java index b2fc404f2..5850eb847 100644 --- a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java +++ b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java @@ -1,865 +1,865 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.spreadsheet.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import org.eclipse.e4.core.contexts.IEclipseContext; -import org.eclipse.e4.ui.di.UISynchronize; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.ui.PlatformUI; -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.mutable.MutableVariant; -import org.simantics.databoard.binding.mutable.Variant; -import org.simantics.db.AsyncReadGraph; -import org.simantics.db.ReadGraph; -import org.simantics.db.RequestProcessor; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.procedure.adapter.AsyncListenerSupport; -import org.simantics.db.common.procedure.adapter.ListenerSupport; -import org.simantics.db.common.procedure.adapter.SyncListenerSupport; -import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; -import org.simantics.db.common.procedure.single.SingleSetSyncListenerDelegate; -import org.simantics.db.common.request.ReadRequest; -import org.simantics.db.common.request.ResourceRead; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.common.request.UniqueRead; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.request.WriteResultRequest; -import org.simantics.db.common.session.SessionEventListenerAdapter; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.StandardRealm; -import org.simantics.db.layer0.request.PossibleURIVariable; -import org.simantics.db.layer0.request.VariableName; -import org.simantics.db.layer0.request.VariableRead; -import org.simantics.db.layer0.variable.ProxyVariables; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.procedure.SyncListener; -import org.simantics.db.request.Write; -import org.simantics.db.service.SessionEventSupport; -import org.simantics.layer0.Layer0; -import org.simantics.spreadsheet.Adaptable; -import org.simantics.spreadsheet.CellEditor; -import org.simantics.spreadsheet.ClientModel; -import org.simantics.spreadsheet.ClientModel.OperationMode; -import org.simantics.spreadsheet.SheetCommands; -import org.simantics.spreadsheet.event.model.RemoveCellHandler; -import org.simantics.spreadsheet.resource.SpreadsheetResource; -import org.simantics.ui.selection.WorkbenchSelectionUtils; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.strings.AlphanumComparator; -import org.simantics.utils.threads.logger.ITask; -import org.simantics.utils.threads.logger.ThreadLogger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.map.hash.TObjectIntHashMap; - -class FilteredVariableProperties extends UnaryRead>> { - - final static String CLASSIFICATION = SpreadsheetResource.URIs.Attribute; - - public FilteredVariableProperties(Variable variable) { - super(variable); - } - - @Override - public Collection> perform(ReadGraph graph) throws DatabaseException { - ArrayList> result = new ArrayList>(); - for(Variable var : parameter.getProperties(graph, CLASSIFICATION)) { - String name = var.getName(graph); - String uri = var.getURI(graph); - result.add(Pair.make(name, var)); - Variable expression = var.getPossibleProperty(graph, "expression"); - if(expression != null) - result.add(Pair.make(name + "#expression", expression)); - Variable editable = var.getPossibleProperty(graph, "editable"); - if(editable != null) - result.add(Pair.make(name + "#editable", editable)); - } - return result; - } - -} - -public class GraphUI implements Adaptable, ListenerSupport, AsyncListenerSupport, SyncListenerSupport { - - private static final Logger LOGGER = LoggerFactory.getLogger(GraphUI.class); - - final public static boolean DEBUG = false; - - final private RequestProcessor processor; - - private CellEditor cellEditor; - - private Variable run; - private ClientModel client; - - private Map listenerCache = new THashMap<>(); - - public GraphUI(RequestProcessor processor) { - this.processor = processor; - } - - public void addCell(ReadGraph graph, Pair child, final ClientModel client) throws DatabaseException { - - if(DEBUG) System.out.println("GraphUI adds cell " + child.second.getURI(graph)); - - final String childName = child.second.getName(graph); - Boolean immutable = child.second.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); - if(immutable != null && immutable) { - Collection properties = child.second.getProperties(graph, FilteredVariableProperties.CLASSIFICATION); - addProperties(graph, properties, client, childName); - } else { - PropertyListener listener = listenerCache.get(child.first); - if (listener == null) { - listener = propertyListener(client, childName); - listenerCache.put(child.first, listener); - } - graph.asyncRequest(new FilteredVariableProperties(child.second), listener); - } - - } - - public void removeCell(ReadGraph graph, Pair child, final ClientModel client) throws DatabaseException { - - if(DEBUG) System.out.println("GraphUI removed cell " + child.first); - - client.clear(child.first); - PropertyListener listener = listenerCache.remove(child.first); - if (listener != null) - listener.dispose(); - - } - - public void loadCells(ReadGraph graph, Variable container, boolean immutable, final ClientModel client) throws DatabaseException { - - if(DEBUG) System.out.println("GraphUI loads cells from " + container.getURI(graph)); - - if(immutable) { - for(Pair cell : graph.syncRequest(new Cells(container), TransientCacheAsyncListener.>>instance())) { - addCell(graph, cell, client); - } - } else { - graph.syncRequest(new Cells(container), new SingleSetSyncListenerDelegate>(GraphUI.this) { - - @Override - public void add(ReadGraph graph, final Pair child) throws DatabaseException { - addCell(graph, child, client); - } - - @Override - public void remove(ReadGraph graph, final Pair child) throws DatabaseException { - removeCell(graph, child, client); - } - }); - } - - } - - private SessionEventListenerAdapter listener; - - private String currentSource; - - private boolean disposed; - - public Resource load(final Variable variable, final ClientModel client) throws DatabaseException { - -// for (PropertyListener listener : listenerCache.values()) -// listener.dispose(); -// -// listenerCache.clear(); - - - - assert(variable != null); - - this.run = variable; - this.client = client; - - SessionEventSupport support = processor.getService(SessionEventSupport.class); - - for (PropertyListener listener : listenerCache.values()) { - listener.dispose(); - } - listenerCache.clear(); - - if(listener != null) - support.removeListener(listener); - - listener = new SessionEventListenerAdapter() { - - @Override - public void writeTransactionFinished() { - client.flush(); - } - - }; - - support.addListener(listener); - - this.cellEditor = processor.sync(new VariableRead>(variable) { - - @Override - public CellEditor perform(ReadGraph graph) throws DatabaseException { - SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph); - return variable.getPropertyValue(graph, SHEET.cellEditor); - } - - }); - - final ITask task = ThreadLogger.getInstance().begin("GraphUI.init"); - - client.clearAll(); - - Map sources = processor.syncRequest(new Sources(variable)); - - List sheetList = processor.syncRequest(new Sheets(variable)); - String currentSheet = processor.syncRequest(new VariableName(variable)); - - Map stateList = processor.syncRequest(new SpreadsheetStates(variable)); - - if(currentSource == null) currentSource = "Sheet"; - - ArrayList sourceList = new ArrayList(sources.keySet()); - - Collections.sort(sourceList, AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); - if(!sourceList.contains(currentSource)) sourceList.add(currentSource); - - client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE, sourceList.toArray(new String[sourceList.size()])); - client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, currentSource); - - client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE, sheetList.toArray(new String[sheetList.size()])); - client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, currentSheet); - - client.setProperty(ClientModel.STATES, ClientModel.STATES_AVAILABLE, stateList.keySet().toArray(new String[stateList.size()])); - - client.setProperty(ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, variable); - - client.setProperty(ClientModel.MODE, ClientModel.MODE_CURRENT, OperationMode.OPERATION); - - String currentState = processor.syncRequest(new UniqueRead() { - - @Override - public String perform(ReadGraph graph) throws DatabaseException { - Resource book = variable.getParent(graph).getRepresents(graph); - Resource ic = graph.getPossibleObject(book, SpreadsheetResource.getInstance(graph).Book_HasDefaultInitialCondition); - if (ic == null) - return ""; - return graph.getRelatedValue2(ic, Layer0.getInstance(graph).HasName, Bindings.STRING); - } - }); - - client.setProperty(ClientModel.STATES, ClientModel.STATES_CURRENT, currentState); - - processor.syncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - - loadCells(graph, variable, false, client); - - graph.syncRequest(new Ranges(variable), new SingleSetSyncListenerDelegate(GraphUI.this) { - - @Override - public void add(ReadGraph graph, final Variable range) throws DatabaseException { - - if(DEBUG) System.out.println("GraphUI adds range " + range.getURI(graph)); - - Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); - loadCells(graph, range, immutable != null && immutable, client); - - } - - @Override - public void remove(ReadGraph graph, final Variable range) throws DatabaseException { - - } - - }); - - - graph.syncRequest(new SheetLines(variable), new SingleSetSyncListenerDelegate(GraphUI.this) { - - @Override - public void add(ReadGraph graph, final Variable range) throws DatabaseException { - - if(DEBUG) System.out.println("GraphUI adds line " + range.getURI(graph)); - - Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); - loadCells(graph, range, immutable != null && immutable, client); - - } - - @Override - public void remove(ReadGraph graph, final Variable range) throws DatabaseException { - - } - }); - - } - -// @Override -// public void remove(ReadGraph graph, Variable child) throws DatabaseException { -// -// String location = locations.get(cellResource); -// assert(location != null); -// -// client.setProperty(location, "Label", null); -// client.setProperty(location, "Expression", null); -// -// } - - }); - - - task.finish(); - client.flush(); - - return null; - - } - - private static class PropertyListener extends SingleSetSyncListenerDelegate> { - - private static final Logger LOGGER = LoggerFactory.getLogger(PropertyListener.class); - - private ClientModel client; - private String childName; - private boolean listenerDisposed; - - public PropertyListener(AsyncListenerSupport support, ClientModel client, String childName) { - super(support); - this.client = client; - this.childName = childName; - } - - @Override - public void add(ReadGraph graph, final Pair property) throws DatabaseException { - - if(DEBUG) - System.out.println("GraphUI adds property " + property.second.getURI(graph)); - - graph.asyncRequest(new CellValue(property.second), new SyncListener() { - - @Override - public void execute(ReadGraph graph, final Object value) throws DatabaseException { - - String propertyName = property.first; - - if(DEBUG) - System.out.println("GraphUI detected content change(1) at " + childName + " - " + propertyName + " -> " + value); - client.setProperty(childName, propertyName, value); - - } - - @Override - public void exception(ReadGraph graph, Throwable throwable) throws DatabaseException { - - LOGGER.error("PropertyListener.exception", throwable); - - String propertyName = property.first; - if("content".equals(propertyName)) { - if(throwable == null) throwable = new Exception(); - String message = throwable.getMessage(); - if(message == null) message = throwable.toString(); - client.setProperty(childName, propertyName, Variant.ofInstance(message)); - } else { - client.setProperty(childName, propertyName, null); - } - - } - - @Override - public boolean isDisposed() { - return listenerDisposed; - } - - }); - } - - public void dispose() { - listenerDisposed = true; - } - - @Override - public String toString() { - return super.toString() + ":" + childName; - } - - } - - private PropertyListener propertyListener(final ClientModel client, final String childName) { - return new PropertyListener(this, client, childName); - } - - private void addProperties(ReadGraph graph, final Collection properties, final ClientModel client, final String childName) throws DatabaseException { - - for(Variable property : properties) { - - if(DEBUG) System.out.println("GraphUI adds immutable property " + property.getURI(graph)); - - final String propertyName = property.getName(graph); - - Object value = property.getValue(graph); - - if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + propertyName + " -> " + value); - client.setProperty(childName, propertyName, value); - - String expression = property.getPossiblePropertyValue(graph, "expression", Bindings.STRING); - if(expression != null) { - if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + (propertyName + "#expression") + " -> " + value); - client.setProperty(childName, propertyName + "#expression", expression); - } - - Boolean editable = property.getPossiblePropertyValue(graph, "editable", Bindings.STRING); - if(editable != null) { - if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + (propertyName + "#editable") + " -> " + value); - client.setProperty(childName, propertyName + "#editable", editable); - } - - } - - } - - @SuppressWarnings("unchecked") - @Override - public T getAdapter(Class clazz) { - - if(Variable.class == clazz) { - - return (T)run; - - } else if(RemoveCellHandler.class == clazz) { - - return (T) new RemoveCellHandler() { - - @Override - public void handle(final String location) { - - processor.asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - - Variable cellVariable = run.getPossibleChild(graph, location); - if(cellVariable != null) { - final Resource config = cellVariable.getPossiblePropertyValue(graph, "Represents"); - if(config != null) { - - graph.asyncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - - Layer0 l0 = Layer0.getInstance(graph); -// SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); - graph.deny(config, l0.PartOf); -// graph.deny(config, sr.RowOf); -// graph.deny(config, sr.ColumnOf); - - } - - }); - - } - } - - } - - }); - - } - - }; - - } else if(CellEditor.class == clazz) { - - return (T)new CellEditor() { - - @Override - public void edit(Transaction transaction, String location, String property, E value, Binding binding, Consumer callback) { - - if (ClientModel.ITERATION_ENABLED.equals(location)) { - Simantics.getSession().asyncRequest(new ReadRequest() { - @Override - public void run(ReadGraph graph) throws DatabaseException { - getBook(graph).setIterationEnabled((boolean)value); - } - }); - return; - } - - if (ClientModel.MODE.equals(location)) { - if (ClientModel.MODE_CURRENT.equals(property)) { - client.setProperty(location, property, value); - client.flush(); - return; - } - } - - if (ClientModel.CONTEXT.equals(location)) { - if(ClientModel.CONTEXT_CURRENT.equals(property)) { - if(value instanceof String) { - try { - Variable newContext = processor.syncRequest(new UnaryRead((String)value) { - - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - - String sheetName = run.getName(graph); - - Variable book = Variables.getContext(graph, run); - Resource bookResource = book.getRepresents(graph); - - Variable input = Variables.getVariable(graph, parameter); - Variable proxy = ProxyVariables.makeProxyVariable(graph, Variables.getVariable(graph, bookResource), input); - - return proxy.getChild(graph, sheetName); - -// return variable.getParent(graph).getChild(graph, parameter); - } - - }); - - load(newContext, client); - return; - } catch (DatabaseException e) { - LOGGER.error("edit failed for model key '" + ClientModel.CONTEXT_CURRENT + "'", e); - } - } - } - } - - if(ClientModel.SHEETS.equals(location)) { - if(ClientModel.SHEETS_CURRENT.equals(property)) { - - if(value instanceof String) { - - try { - - Variable newInput = processor.syncRequest(new UnaryRead((String)value) { - - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - return run.getParent(graph).getChild(graph, parameter); - } - - }); - - load(newInput, client); - return; - } catch (DatabaseException e) { - LOGGER.error("edit failed for model key '" + ClientModel.SHEETS_CURRENT + "'", e); - } - } - } - } - - if(ClientModel.STATES.equals(location)) { - if(ClientModel.STATES_CURRENT.equals(property)) { - if(value instanceof String) { - final String parameter = (String) value; - try { - - String uri = processor.syncRequest(new WriteResultRequest() { - - @Override - public String perform(WriteGraph graph) throws DatabaseException { - - Map states = graph.syncRequest(new SpreadsheetStates(run)); - - Resource state = null; - for (Map.Entry entry : states.entrySet()) { - if (entry.getKey().equals(parameter)) { - state = entry.getValue(); - break; - } - } - if (state != null) { - Variable context = Variables.getContext(graph, run); - Resource bookResource = context.getRepresents(graph); - SpreadsheetGraphUtils.setDefaultInitialConditionForBook(graph, bookResource, state); - - String contextURI = context.getURI(graph); - - String sessionName = context.getParent(graph).getURI(graph); - SpreadsheetSessionManager.getInstance().removeRealm(sessionName); - SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName); - } - - return run.getURI(graph); - } - }); - Variable newInput = processor.syncRequest(new PossibleURIVariable(uri)); - load(newInput, client); -// fullSynchronize(); - return; - } catch (DatabaseException e) { - LOGGER.error("edit failed for model key '" + ClientModel.STATES_CURRENT + "'", e); - } - } - } - } - - if(ClientModel.SOURCES.equals(location)) { - if(ClientModel.SOURCES_CURRENT.equals(property)) { - try { - Resource res = WorkbenchSelectionUtils.getPossibleResource(value); - if(res != null) { - - Variable newInput = processor.syncRequest(new ResourceRead(res) { - - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - Variable base = ProxyVariables.proxyVariableBase(graph, run); - Variable in = Variables.getVariable(graph, resource); - currentSource = in.getURI(graph); - return ProxyVariables.makeProxyVariable(graph, base, in); - } - - }); - - load(newInput, client); - - return; - - } else if(value instanceof String) { - - Variable newInput = processor.syncRequest(new UnaryRead((String)value) { - - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - - Variable base = ProxyVariables.proxyVariableBase(graph, run); - Map sources = graph.syncRequest(new Sources(base)); - - Variable found = sources.get(parameter); - if(found == null) return null; - - currentSource = parameter; - - return ProxyVariables.makeProxyVariable(graph, base, found); - - } - - }); - - load(newInput, client); - return; - } - - } catch (DatabaseException e) { - LOGGER.error("edit failed for model key '" + ClientModel.SOURCES_CURRENT + "'", e); - } - } - return; - } - boolean needsCommit = false; - if (transaction == null) { - OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); - transaction = startTransaction(mode); -// if (mode.equals(OperationMode.OPERATION)) - transaction.setContext(run); - needsCommit = true; - } - final Transaction finalTransaction = transaction; - cellEditor.edit(transaction, location, property, value, binding, new Consumer() { - - @Override - public void accept(Object param) { - if (finalTransaction.needSynchronization() != null) - synchronize(finalTransaction.needSynchronization()); - } - }); - if (needsCommit) - transaction.commit(); - } - - @Override - public void edit(Transaction transaction, String location, Variant variant, Consumer callback) { - boolean needsCommit = false; - if (transaction == null) { - OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); - transaction = startTransaction(mode); -// if (mode.equals(OperationMode.OPERATION)) - transaction.setContext(run); - needsCommit = true; - } - final Transaction finalTransaction = transaction; - cellEditor.edit(transaction, location, variant, new Consumer() { - - @Override - public void accept(Object param) { - if (finalTransaction.needSynchronization() != null) - synchronize(finalTransaction.needSynchronization()); - } - }); - if (needsCommit) - transaction.commit(); - } - - @Override - public void copy(final Transaction transaction, String location, MutableVariant variant, Consumer callback) { - cellEditor.edit(transaction, location, variant, new Consumer() { - - @Override - public void accept(Object param) { - if (transaction.needSynchronization() != null) - synchronize(transaction.needSynchronization()); - } - }); - } - - @Override - public Transaction startTransaction(OperationMode mode) { - return cellEditor.startTransaction(mode); - } - - }; - - } else if (SheetCommands.class == clazz ) { - - return (T) new SheetCommands() { - - @Override - public void saveState() { - - Simantics.getSession().asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - IEclipseContext context = PlatformUI.getWorkbench().getService(IEclipseContext.class); - - Resource uiContextResource = run.getRepresents(graph); - Resource bookResource = Variables.getContext(graph, run).getRepresents(graph); - Layer0 L0 = Layer0.getInstance(graph); - String uiContextName = graph.getRelatedValue2(uiContextResource, L0.HasName, Bindings.STRING); - String bookName = graph.getRelatedValue2(bookResource, L0.HasName, Bindings.STRING); - - UISynchronize synchronizer = context.get(UISynchronize.class); - synchronizer.asyncExec(() -> { - Pair[] pairs = new Pair[] {Pair.make(uiContextName, uiContextResource), Pair.make(bookName, bookResource) }; - SaveSpreadsheetStateDialog dialog = new SaveSpreadsheetStateDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getSite(), "Save Spreadsheet state", pairs); - if (dialog.open() == Dialog.OK) { - Object[] result = dialog.getSelection(); - if (result != null) { - Pair p = (Pair) result[0]; - Simantics.getSession().asyncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - - Variable parent = run.getParent(graph); - Variable base = ProxyVariables.proxyVariableBase(graph, parent); - SpreadsheetGraphUtils.saveInitialCondition(graph, parent, p.first, p.second); - } - }); - } - } else { - return; - } - }); - } - }); - } - }; - } - - return null; - - } - - @Override - public void exception(Throwable t) { - t.printStackTrace(); - } - - @Override - public boolean isDisposed() { - return disposed; - } - - @Override - public void exception(AsyncReadGraph graph, Throwable t) { - LOGGER.error("Failed to read properties.", t); - } - - @Override - public void exception(ReadGraph graph, Throwable t) { - LOGGER.error("Failed to read properties.", t); - } - - public void dispose() { - for (PropertyListener listener : listenerCache.values()) - listener.dispose(); - - listenerCache.clear(); - SessionEventSupport support = processor.getService(SessionEventSupport.class); - support.removeListener(listener); - disposed = true; - } - - private void synchronize(List list) { - Simantics.getSession().asyncRequest(new FullSynchronizeBook(run, list)); - } - - public static class FullSynchronizeBook extends ReadRequest { - - private final Variable run; - private final List location; - - public FullSynchronizeBook(Variable run, List cellLocation) { - this.run = run; - this.location = cellLocation; - } - - @Override - public void run(ReadGraph graph) throws DatabaseException { - String uri = run.getURI(graph); - String parentUri = run.getParent(graph).getURI(graph); - System.err.println("Full sync for book " + parentUri); - - Resource sheetResource = run.getRepresents(graph); - Variable sheetVariable = Variables.getVariable(graph, sheetResource); - - TObjectIntHashMap changes = null; - if (location != null) { - changes = new TObjectIntHashMap<>(location.size()); - for (Object loc : location) { - Variable var = (Variable) loc; - changes.put(var, 1); - }; - } - SpreadsheetGraphUtils.partialSynchronization(graph, run.getParent(graph), changes); - } - - } - - private SpreadsheetBook getBook(ReadGraph graph) throws DatabaseException { - String sessionName = run.getParent(graph).getParent(graph).getURI(graph); - StandardRealm realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName); - SpreadsheetBook book = realm.getEngine(); - return book; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.spreadsheet.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import org.eclipse.e4.core.contexts.IEclipseContext; +import org.eclipse.e4.ui.di.UISynchronize; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.ui.PlatformUI; +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.mutable.MutableVariant; +import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.adapter.AsyncListenerSupport; +import org.simantics.db.common.procedure.adapter.ListenerSupport; +import org.simantics.db.common.procedure.adapter.SyncListenerSupport; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.procedure.single.SingleSetSyncListenerDelegate; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.request.WriteResultRequest; +import org.simantics.db.common.session.SessionEventListenerAdapter; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.StandardRealm; +import org.simantics.db.layer0.request.PossibleURIVariable; +import org.simantics.db.layer0.request.VariableName; +import org.simantics.db.layer0.request.VariableRead; +import org.simantics.db.layer0.variable.ProxyVariables; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.procedure.SyncListener; +import org.simantics.db.request.Write; +import org.simantics.db.service.SessionEventSupport; +import org.simantics.layer0.Layer0; +import org.simantics.spreadsheet.Adaptable; +import org.simantics.spreadsheet.CellEditor; +import org.simantics.spreadsheet.ClientModel; +import org.simantics.spreadsheet.ClientModel.OperationMode; +import org.simantics.spreadsheet.SheetCommands; +import org.simantics.spreadsheet.event.model.RemoveCellHandler; +import org.simantics.spreadsheet.resource.SpreadsheetResource; +import org.simantics.ui.selection.WorkbenchSelectionUtils; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.strings.AlphanumComparator; +import org.simantics.utils.threads.logger.ITask; +import org.simantics.utils.threads.logger.ThreadLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.map.hash.TObjectIntHashMap; + +class FilteredVariableProperties extends UnaryRead>> { + + final static String CLASSIFICATION = SpreadsheetResource.URIs.Attribute; + + public FilteredVariableProperties(Variable variable) { + super(variable); + } + + @Override + public Collection> perform(ReadGraph graph) throws DatabaseException { + ArrayList> result = new ArrayList>(); + for(Variable var : parameter.getProperties(graph, CLASSIFICATION)) { + String name = var.getName(graph); + String uri = var.getURI(graph); + result.add(Pair.make(name, var)); + Variable expression = var.getPossibleProperty(graph, "expression"); + if(expression != null) + result.add(Pair.make(name + "#expression", expression)); + Variable editable = var.getPossibleProperty(graph, "editable"); + if(editable != null) + result.add(Pair.make(name + "#editable", editable)); + } + return result; + } + +} + +public class GraphUI implements Adaptable, ListenerSupport, AsyncListenerSupport, SyncListenerSupport { + + private static final Logger LOGGER = LoggerFactory.getLogger(GraphUI.class); + + final public static boolean DEBUG = false; + + final private RequestProcessor processor; + + private CellEditor cellEditor; + + private Variable run; + private ClientModel client; + + private Map listenerCache = new THashMap<>(); + + public GraphUI(RequestProcessor processor) { + this.processor = processor; + } + + public void addCell(ReadGraph graph, Pair child, final ClientModel client) throws DatabaseException { + + if(DEBUG) System.out.println("GraphUI adds cell " + child.second.getURI(graph)); + + final String childName = child.second.getName(graph); + Boolean immutable = child.second.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); + if(immutable != null && immutable) { + Collection properties = child.second.getProperties(graph, FilteredVariableProperties.CLASSIFICATION); + addProperties(graph, properties, client, childName); + } else { + PropertyListener listener = listenerCache.get(child.first); + if (listener == null) { + listener = propertyListener(client, childName); + listenerCache.put(child.first, listener); + } + graph.asyncRequest(new FilteredVariableProperties(child.second), listener); + } + + } + + public void removeCell(ReadGraph graph, Pair child, final ClientModel client) throws DatabaseException { + + if(DEBUG) System.out.println("GraphUI removed cell " + child.first); + + client.clear(child.first); + PropertyListener listener = listenerCache.remove(child.first); + if (listener != null) + listener.dispose(); + + } + + public void loadCells(ReadGraph graph, Variable container, boolean immutable, final ClientModel client) throws DatabaseException { + + if(DEBUG) System.out.println("GraphUI loads cells from " + container.getURI(graph)); + + if(immutable) { + for(Pair cell : graph.syncRequest(new Cells(container), TransientCacheAsyncListener.>>instance())) { + addCell(graph, cell, client); + } + } else { + graph.syncRequest(new Cells(container), new SingleSetSyncListenerDelegate>(GraphUI.this) { + + @Override + public void add(ReadGraph graph, final Pair child) throws DatabaseException { + addCell(graph, child, client); + } + + @Override + public void remove(ReadGraph graph, final Pair child) throws DatabaseException { + removeCell(graph, child, client); + } + }); + } + + } + + private SessionEventListenerAdapter listener; + + private String currentSource; + + private boolean disposed; + + public Resource load(final Variable variable, final ClientModel client) throws DatabaseException { + +// for (PropertyListener listener : listenerCache.values()) +// listener.dispose(); +// +// listenerCache.clear(); + + + + assert(variable != null); + + this.run = variable; + this.client = client; + + SessionEventSupport support = processor.getService(SessionEventSupport.class); + + for (PropertyListener listener : listenerCache.values()) { + listener.dispose(); + } + listenerCache.clear(); + + if(listener != null) + support.removeListener(listener); + + listener = new SessionEventListenerAdapter() { + + @Override + public void writeTransactionFinished() { + client.flush(); + } + + }; + + support.addListener(listener); + + this.cellEditor = processor.sync(new VariableRead>(variable) { + + @Override + public CellEditor perform(ReadGraph graph) throws DatabaseException { + SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph); + return variable.getPropertyValue(graph, SHEET.cellEditor); + } + + }); + + final ITask task = ThreadLogger.getInstance().begin("GraphUI.init"); + + client.clearAll(); + + Map sources = processor.syncRequest(new Sources(variable)); + + List sheetList = processor.syncRequest(new Sheets(variable)); + String currentSheet = processor.syncRequest(new VariableName(variable)); + + Map stateList = processor.syncRequest(new SpreadsheetStates(variable)); + + if(currentSource == null) currentSource = "Sheet"; + + ArrayList sourceList = new ArrayList(sources.keySet()); + + Collections.sort(sourceList, AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + if(!sourceList.contains(currentSource)) sourceList.add(currentSource); + + client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_AVAILABLE, sourceList.toArray(new String[sourceList.size()])); + client.setProperty(ClientModel.SOURCES, ClientModel.SOURCES_CURRENT, currentSource); + + client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_AVAILABLE, sheetList.toArray(new String[sheetList.size()])); + client.setProperty(ClientModel.SHEETS, ClientModel.SHEETS_CURRENT, currentSheet); + + client.setProperty(ClientModel.STATES, ClientModel.STATES_AVAILABLE, stateList.keySet().toArray(new String[stateList.size()])); + + client.setProperty(ClientModel.CONTEXT, ClientModel.CONTEXT_CURRENT, variable); + + client.setProperty(ClientModel.MODE, ClientModel.MODE_CURRENT, OperationMode.OPERATION); + + String currentState = processor.syncRequest(new UniqueRead() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + Resource book = variable.getParent(graph).getRepresents(graph); + Resource ic = graph.getPossibleObject(book, SpreadsheetResource.getInstance(graph).Book_HasDefaultInitialCondition); + if (ic == null) + return ""; + return graph.getRelatedValue2(ic, Layer0.getInstance(graph).HasName, Bindings.STRING); + } + }); + + client.setProperty(ClientModel.STATES, ClientModel.STATES_CURRENT, currentState); + + processor.syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + + loadCells(graph, variable, false, client); + + graph.syncRequest(new Ranges(variable), new SingleSetSyncListenerDelegate(GraphUI.this) { + + @Override + public void add(ReadGraph graph, final Variable range) throws DatabaseException { + + if(DEBUG) System.out.println("GraphUI adds range " + range.getURI(graph)); + + Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); + loadCells(graph, range, immutable != null && immutable, client); + + } + + @Override + public void remove(ReadGraph graph, final Variable range) throws DatabaseException { + + } + + }); + + + graph.syncRequest(new SheetLines(variable), new SingleSetSyncListenerDelegate(GraphUI.this) { + + @Override + public void add(ReadGraph graph, final Variable range) throws DatabaseException { + + if(DEBUG) System.out.println("GraphUI adds line " + range.getURI(graph)); + + Boolean immutable = range.getPossiblePropertyValue(graph, "immutable", Bindings.BOOLEAN); + loadCells(graph, range, immutable != null && immutable, client); + + } + + @Override + public void remove(ReadGraph graph, final Variable range) throws DatabaseException { + + } + }); + + } + +// @Override +// public void remove(ReadGraph graph, Variable child) throws DatabaseException { +// +// String location = locations.get(cellResource); +// assert(location != null); +// +// client.setProperty(location, "Label", null); +// client.setProperty(location, "Expression", null); +// +// } + + }); + + + task.finish(); + client.flush(); + + return null; + + } + + private static class PropertyListener extends SingleSetSyncListenerDelegate> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PropertyListener.class); + + private ClientModel client; + private String childName; + private boolean listenerDisposed; + + public PropertyListener(AsyncListenerSupport support, ClientModel client, String childName) { + super(support); + this.client = client; + this.childName = childName; + } + + @Override + public void add(ReadGraph graph, final Pair property) throws DatabaseException { + + if(DEBUG) + System.out.println("GraphUI adds property " + property.second.getURI(graph)); + + graph.asyncRequest(new CellValue(property.second), new SyncListener() { + + @Override + public void execute(ReadGraph graph, final Object value) throws DatabaseException { + + String propertyName = property.first; + + if(DEBUG) + System.out.println("GraphUI detected content change(1) at " + childName + " - " + propertyName + " -> " + value); + client.setProperty(childName, propertyName, value); + + } + + @Override + public void exception(ReadGraph graph, Throwable throwable) throws DatabaseException { + + LOGGER.error("PropertyListener.exception", throwable); + + String propertyName = property.first; + if("content".equals(propertyName)) { + if(throwable == null) throwable = new Exception(); + String message = throwable.getMessage(); + if(message == null) message = throwable.toString(); + client.setProperty(childName, propertyName, Variant.ofInstance(message)); + } else { + client.setProperty(childName, propertyName, null); + } + + } + + @Override + public boolean isDisposed() { + return listenerDisposed; + } + + }); + } + + public void dispose() { + listenerDisposed = true; + } + + @Override + public String toString() { + return super.toString() + ":" + childName; + } + + } + + private PropertyListener propertyListener(final ClientModel client, final String childName) { + return new PropertyListener(this, client, childName); + } + + private void addProperties(ReadGraph graph, final Collection properties, final ClientModel client, final String childName) throws DatabaseException { + + for(Variable property : properties) { + + if(DEBUG) System.out.println("GraphUI adds immutable property " + property.getURI(graph)); + + final String propertyName = property.getName(graph); + + Object value = property.getValue(graph); + + if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + propertyName + " -> " + value); + client.setProperty(childName, propertyName, value); + + String expression = property.getPossiblePropertyValue(graph, "expression", Bindings.STRING); + if(expression != null) { + if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + (propertyName + "#expression") + " -> " + value); + client.setProperty(childName, propertyName + "#expression", expression); + } + + Boolean editable = property.getPossiblePropertyValue(graph, "editable", Bindings.STRING); + if(editable != null) { + if(DEBUG) System.out.println("GraphUI detected change at " + childName + " - " + (propertyName + "#editable") + " -> " + value); + client.setProperty(childName, propertyName + "#editable", editable); + } + + } + + } + + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Class clazz) { + + if(Variable.class == clazz) { + + return (T)run; + + } else if(RemoveCellHandler.class == clazz) { + + return (T) new RemoveCellHandler() { + + @Override + public void handle(final String location) { + + processor.asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + + Variable cellVariable = run.getPossibleChild(graph, location); + if(cellVariable != null) { + final Resource config = cellVariable.getPossiblePropertyValue(graph, "Represents"); + if(config != null) { + + graph.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + + Layer0 l0 = Layer0.getInstance(graph); +// SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); + graph.deny(config, l0.PartOf); +// graph.deny(config, sr.RowOf); +// graph.deny(config, sr.ColumnOf); + + } + + }); + + } + } + + } + + }); + + } + + }; + + } else if(CellEditor.class == clazz) { + + return (T)new CellEditor() { + + @Override + public void edit(Transaction transaction, String location, String property, E value, Binding binding, Consumer callback) { + + if (ClientModel.ITERATION_ENABLED.equals(location)) { + Simantics.getSession().asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + getBook(graph).setIterationEnabled((boolean)value); + } + }); + return; + } + + if (ClientModel.MODE.equals(location)) { + if (ClientModel.MODE_CURRENT.equals(property)) { + client.setProperty(location, property, value); + client.flush(); + return; + } + } + + if (ClientModel.CONTEXT.equals(location)) { + if(ClientModel.CONTEXT_CURRENT.equals(property)) { + if(value instanceof String) { + try { + Variable newContext = processor.syncRequest(new UnaryRead((String)value) { + + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + + String sheetName = run.getName(graph); + + Variable book = Variables.getContext(graph, run); + Resource bookResource = book.getRepresents(graph); + + Variable input = Variables.getVariable(graph, parameter); + Variable proxy = ProxyVariables.makeProxyVariable(graph, Variables.getVariable(graph, bookResource), input); + + return proxy.getChild(graph, sheetName); + +// return variable.getParent(graph).getChild(graph, parameter); + } + + }); + + load(newContext, client); + return; + } catch (DatabaseException e) { + LOGGER.error("edit failed for model key '" + ClientModel.CONTEXT_CURRENT + "'", e); + } + } + } + } + + if(ClientModel.SHEETS.equals(location)) { + if(ClientModel.SHEETS_CURRENT.equals(property)) { + + if(value instanceof String) { + + try { + + Variable newInput = processor.syncRequest(new UnaryRead((String)value) { + + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + return run.getParent(graph).getChild(graph, parameter); + } + + }); + + load(newInput, client); + return; + } catch (DatabaseException e) { + LOGGER.error("edit failed for model key '" + ClientModel.SHEETS_CURRENT + "'", e); + } + } + } + } + + if(ClientModel.STATES.equals(location)) { + if(ClientModel.STATES_CURRENT.equals(property)) { + if(value instanceof String) { + final String parameter = (String) value; + try { + + String uri = processor.syncRequest(new WriteResultRequest() { + + @Override + public String perform(WriteGraph graph) throws DatabaseException { + + Map states = graph.syncRequest(new SpreadsheetStates(run)); + + Resource state = null; + for (Map.Entry entry : states.entrySet()) { + if (entry.getKey().equals(parameter)) { + state = entry.getValue(); + break; + } + } + if (state != null) { + Variable context = Variables.getContext(graph, run); + Resource bookResource = context.getRepresents(graph); + SpreadsheetGraphUtils.setDefaultInitialConditionForBook(graph, bookResource, state); + + String contextURI = context.getURI(graph); + + String sessionName = context.getParent(graph).getURI(graph); + SpreadsheetSessionManager.getInstance().removeRealm(graph, sessionName); + SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName); + } + + return run.getURI(graph); + } + }); + Variable newInput = processor.syncRequest(new PossibleURIVariable(uri)); + load(newInput, client); +// fullSynchronize(); + return; + } catch (DatabaseException e) { + LOGGER.error("edit failed for model key '" + ClientModel.STATES_CURRENT + "'", e); + } + } + } + } + + if(ClientModel.SOURCES.equals(location)) { + if(ClientModel.SOURCES_CURRENT.equals(property)) { + try { + Resource res = WorkbenchSelectionUtils.getPossibleResource(value); + if(res != null) { + + Variable newInput = processor.syncRequest(new ResourceRead(res) { + + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + Variable base = ProxyVariables.proxyVariableBase(graph, run); + Variable in = Variables.getVariable(graph, resource); + currentSource = in.getURI(graph); + return ProxyVariables.makeProxyVariable(graph, base, in); + } + + }); + + load(newInput, client); + + return; + + } else if(value instanceof String) { + + Variable newInput = processor.syncRequest(new UnaryRead((String)value) { + + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + + Variable base = ProxyVariables.proxyVariableBase(graph, run); + Map sources = graph.syncRequest(new Sources(base)); + + Variable found = sources.get(parameter); + if(found == null) return null; + + currentSource = parameter; + + return ProxyVariables.makeProxyVariable(graph, base, found); + + } + + }); + + load(newInput, client); + return; + } + + } catch (DatabaseException e) { + LOGGER.error("edit failed for model key '" + ClientModel.SOURCES_CURRENT + "'", e); + } + } + return; + } + boolean needsCommit = false; + if (transaction == null) { + OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); + transaction = startTransaction(mode); +// if (mode.equals(OperationMode.OPERATION)) + transaction.setContext(run); + needsCommit = true; + } + final Transaction finalTransaction = transaction; + cellEditor.edit(transaction, location, property, value, binding, new Consumer() { + + @Override + public void accept(Object param) { + if (finalTransaction.needSynchronization() != null) + synchronize(finalTransaction.needSynchronization()); + } + }); + if (needsCommit) + transaction.commit(); + } + + @Override + public void edit(Transaction transaction, String location, Variant variant, Consumer callback) { + boolean needsCommit = false; + if (transaction == null) { + OperationMode mode = client.getPropertyAt(ClientModel.MODE, ClientModel.MODE_CURRENT); + transaction = startTransaction(mode); +// if (mode.equals(OperationMode.OPERATION)) + transaction.setContext(run); + needsCommit = true; + } + final Transaction finalTransaction = transaction; + cellEditor.edit(transaction, location, variant, new Consumer() { + + @Override + public void accept(Object param) { + if (finalTransaction.needSynchronization() != null) + synchronize(finalTransaction.needSynchronization()); + } + }); + if (needsCommit) + transaction.commit(); + } + + @Override + public void copy(final Transaction transaction, String location, MutableVariant variant, Consumer callback) { + cellEditor.edit(transaction, location, variant, new Consumer() { + + @Override + public void accept(Object param) { + if (transaction.needSynchronization() != null) + synchronize(transaction.needSynchronization()); + } + }); + } + + @Override + public Transaction startTransaction(OperationMode mode) { + return cellEditor.startTransaction(mode); + } + + }; + + } else if (SheetCommands.class == clazz ) { + + return (T) new SheetCommands() { + + @Override + public void saveState() { + + Simantics.getSession().asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + IEclipseContext context = PlatformUI.getWorkbench().getService(IEclipseContext.class); + + Resource uiContextResource = run.getRepresents(graph); + Resource bookResource = Variables.getContext(graph, run).getRepresents(graph); + Layer0 L0 = Layer0.getInstance(graph); + String uiContextName = graph.getRelatedValue2(uiContextResource, L0.HasName, Bindings.STRING); + String bookName = graph.getRelatedValue2(bookResource, L0.HasName, Bindings.STRING); + + UISynchronize synchronizer = context.get(UISynchronize.class); + synchronizer.asyncExec(() -> { + Pair[] pairs = new Pair[] {Pair.make(uiContextName, uiContextResource), Pair.make(bookName, bookResource) }; + SaveSpreadsheetStateDialog dialog = new SaveSpreadsheetStateDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getSite(), "Save Spreadsheet state", pairs); + if (dialog.open() == Dialog.OK) { + Object[] result = dialog.getSelection(); + if (result != null) { + Pair p = (Pair) result[0]; + Simantics.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + + Variable parent = run.getParent(graph); + Variable base = ProxyVariables.proxyVariableBase(graph, parent); + SpreadsheetGraphUtils.saveInitialCondition(graph, parent, p.first, p.second); + } + }); + } + } else { + return; + } + }); + } + }); + } + }; + } + + return null; + + } + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public boolean isDisposed() { + return disposed; + } + + @Override + public void exception(AsyncReadGraph graph, Throwable t) { + LOGGER.error("Failed to read properties.", t); + } + + @Override + public void exception(ReadGraph graph, Throwable t) { + LOGGER.error("Failed to read properties.", t); + } + + public void dispose() { + for (PropertyListener listener : listenerCache.values()) + listener.dispose(); + + listenerCache.clear(); + SessionEventSupport support = processor.getService(SessionEventSupport.class); + support.removeListener(listener); + disposed = true; + } + + private void synchronize(List list) { + Simantics.getSession().asyncRequest(new FullSynchronizeBook(run, list)); + } + + public static class FullSynchronizeBook extends ReadRequest { + + private final Variable run; + private final List location; + + public FullSynchronizeBook(Variable run, List cellLocation) { + this.run = run; + this.location = cellLocation; + } + + @Override + public void run(ReadGraph graph) throws DatabaseException { + String uri = run.getURI(graph); + String parentUri = run.getParent(graph).getURI(graph); + System.err.println("Full sync for book " + parentUri); + + Resource sheetResource = run.getRepresents(graph); + Variable sheetVariable = Variables.getVariable(graph, sheetResource); + + TObjectIntHashMap changes = null; + if (location != null) { + changes = new TObjectIntHashMap<>(location.size()); + for (Object loc : location) { + Variable var = (Variable) loc; + changes.put(var, 1); + }; + } + SpreadsheetGraphUtils.partialSynchronization(graph, run.getParent(graph), changes); + } + + } + + private SpreadsheetBook getBook(ReadGraph graph) throws DatabaseException { + String sessionName = run.getParent(graph).getParent(graph).getURI(graph); + StandardRealm realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName); + SpreadsheetBook book = realm.getEngine(); + return book; + } + +}