1 package org.simantics.spreadsheet.graph;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.ObjectOutputStream;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
15 import javax.xml.soap.Node;
17 import org.simantics.Simantics;
18 import org.simantics.databoard.Bindings;
19 import org.simantics.databoard.binding.mutable.Variant;
20 import org.simantics.databoard.util.binary.RandomAccessBinary;
21 import org.simantics.datatypes.DatatypeResource;
22 import org.simantics.datatypes.literal.Font;
23 import org.simantics.datatypes.literal.RGB;
24 import org.simantics.datatypes.utils.BTree;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.WriteGraph;
28 import org.simantics.db.common.request.BinaryRead;
29 import org.simantics.db.common.request.ObjectsWithType;
30 import org.simantics.db.common.request.UnaryRead;
31 import org.simantics.db.common.request.WriteRequest;
32 import org.simantics.db.common.utils.LiteralFileUtil;
33 import org.simantics.db.exception.DatabaseException;
34 import org.simantics.db.exception.ServiceException;
35 import org.simantics.db.layer0.util.Layer0Utils;
36 import org.simantics.db.layer0.variable.StandardGraphChildVariable;
37 import org.simantics.db.layer0.variable.Variable;
38 import org.simantics.db.layer0.variable.VariableNode;
39 import org.simantics.db.layer0.variable.Variables;
40 import org.simantics.db.procedure.Listener;
41 import org.simantics.db.service.ClusteringSupport;
42 import org.simantics.layer0.Layer0;
43 import org.simantics.scl.runtime.SCLContext;
44 import org.simantics.scl.runtime.function.Function;
45 import org.simantics.scl.runtime.function.Function1;
46 import org.simantics.scl.runtime.tuple.Tuple;
47 import org.simantics.scl.runtime.tuple.Tuple0;
48 import org.simantics.scl.runtime.tuple.Tuple2;
49 import org.simantics.simulator.toolkit.StandardRealm;
50 import org.simantics.spreadsheet.CellEditor;
51 import org.simantics.spreadsheet.ExternalRef;
52 import org.simantics.spreadsheet.OperationMode;
53 import org.simantics.spreadsheet.Range;
54 import org.simantics.spreadsheet.Spreadsheets;
55 import org.simantics.spreadsheet.Transaction;
56 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
57 import org.simantics.spreadsheet.resource.SpreadsheetResource;
58 import org.simantics.spreadsheet.solver.SheetNode;
59 import org.simantics.spreadsheet.solver.SpreadsheetBook;
60 import org.simantics.spreadsheet.solver.SpreadsheetCell;
61 import org.simantics.spreadsheet.solver.SpreadsheetEngine;
62 import org.simantics.spreadsheet.solver.SpreadsheetLine;
63 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
64 import org.simantics.spreadsheet.util.SpreadsheetUtils;
65 import org.simantics.structural.synchronization.client.Synchronizer;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 import gnu.trove.iterator.TObjectIntIterator;
70 import gnu.trove.map.hash.TObjectIntHashMap;
72 public class SpreadsheetGraphUtils {
74 private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetGraphUtils.class);
76 public static File extractInitialCondition(ReadGraph graph, Resource ic) throws DatabaseException, IOException {
78 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
80 File temp = Simantics.getTempfile("excel","ic");
82 LiteralFileUtil.copyRandomAccessBinaryToFile(graph, ic, SR.InitialCondition_bytes, temp);
83 if (temp.length() == 0)
84 throw new FileNotFoundException("Snapshot file does not exist.\nThis seems to be a database bug that manifests as total loss of state file data.\nThis error prevents the program from crashing.");
90 public static RandomAccessBinary getOrCreateRandomAccessBinary(WriteGraph graph, Resource initialCondition) throws DatabaseException, IOException {
92 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
94 // We put snapshot literals in their own clusters for now just to be safe
95 Resource literal = graph.getPossibleObject(initialCondition, SR.InitialCondition_bytes);
96 if (literal != null) {
97 RandomAccessBinary rab = graph.getRandomAccessBinary(literal);
99 rab.removeBytes(rab.length(), RandomAccessBinary.ByteSide.Right);
102 Layer0 L0 = Layer0.getInstance(graph);
103 ClusteringSupport cs = graph.getService(ClusteringSupport.class);
104 literal = graph.newResource(cs.createCluster());
105 graph.claim(literal, L0.InstanceOf, null, L0.ByteArray);
106 graph.claim(initialCondition, SR.InitialCondition_bytes, SR.InitialCondition_bytes_Inverse, literal);
107 return graph.createRandomAccessBinary(literal, Bindings.BYTE_ARRAY.type(), null);
111 public static Resource saveInitialCondition(WriteGraph graph, Variable run, Resource container, String name) throws DatabaseException {
113 String sessionName = run.getParent(graph).getURI(graph);
115 Resource bookResource = run.getRepresents(graph);
117 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
118 SpreadsheetBook book = realm.getEngine();
122 File temp = Simantics.getTempfile("excel", "ic");
123 System.err.println("Saving initial condition to " + temp.getAbsolutePath());
125 FileOutputStream fileOut = new FileOutputStream(temp);
126 ObjectOutputStream out = new ObjectOutputStream(fileOut);
127 out.writeObject(book);
131 Layer0 L0 = Layer0.getInstance(graph);
132 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
133 Resource ic = graph.newResource();
134 graph.claim(ic, L0.InstanceOf, SR.InitialCondition);
135 graph.addLiteral(ic, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING);
137 RandomAccessBinary rab = getOrCreateRandomAccessBinary(graph, ic);
138 LiteralFileUtil.copyRandomAccessBinaryFromFile(temp, rab);
140 graph.claim(container, L0.ConsistsOf, L0.PartOf, ic);
142 graph.deny(bookResource, SR.HasInitialCondition);
143 graph.claim(bookResource, SR.HasInitialCondition, ic);
144 graph.claim(ic, SR.InitialCondition_ConditionOf, bookResource);
146 setDefaultInitialConditionForBook(graph, bookResource, ic);
150 } catch (IOException e) {
152 throw new DatabaseException(e);
157 public static void setDefaultInitialConditionForBook(WriteGraph graph, Resource book, Resource ic) throws ServiceException {
158 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
159 graph.deny(book, SR.Book_HasDefaultInitialCondition);
160 graph.claim(ic, SR.InitialCondition_DefaultConditionOf, book);
163 public static void evaluateAll(ReadGraph graph, Variable run) throws DatabaseException {
165 String sessionName = run.getParent(graph).getURI(graph);
166 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
167 SpreadsheetBook book = realm.getEngine();
168 book.accept(new EvaluateAll(book));
172 public static void invalidateAll(ReadGraph graph, Variable run) throws DatabaseException {
174 String sessionName = run.getParent(graph).getURI(graph);
175 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
176 SpreadsheetBook book = realm.getEngine();
177 book.accept(new InvalidateAll());
178 realm.getNodeManager().refreshVariables();
182 public static boolean fullSynchronization(ReadGraph graph, Variable run) throws DatabaseException {
183 return partialSynchronization(graph, run, null);
186 public static boolean partialSynchronization(ReadGraph graph, Variable run, TObjectIntHashMap<Variable> changeFlags) throws DatabaseException {
188 Synchronizer synchronizer = new Synchronizer(graph);
189 String sessionName = run.getParent(graph).getURI(graph);
191 Resource bookResource = run.getRepresents(graph);
192 Variable configuration = Variables.getVariable(graph, bookResource);
194 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
195 SpreadsheetBook book = realm.getEngine();
197 SpreadsheetSynchronizationEventHandler handler = new SpreadsheetSynchronizationEventHandler(graph, book);
199 if (changeFlags == null) {
200 synchronizer.fullSynchronization(configuration, handler);
203 TObjectIntIterator<Variable> iter = changeFlags.iterator();
205 Variable row = iter.key();
207 Variable rowParent = row.getParent(graph);
208 while (!rowParent.equals(configuration)) {
209 changeFlags.put(rowParent, 1);
210 rowParent = rowParent.getParent(graph);
213 changeFlags.put(configuration, 1);
215 synchronizer.partialSynchronization(configuration, handler, changeFlags);
218 realm.getNodeManager().fireNodeListeners();
219 return handler.getDidChanges();
223 public static Variable findCell(ReadGraph graph, Variable run, String reference) throws DatabaseException {
225 int pos = reference.indexOf("!");
226 String sheetName = reference.substring(0, pos);
227 String cellName = reference.substring(pos+1);
229 String sessionName = run.getParent(graph).getURI(graph);
230 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
231 SpreadsheetBook book = realm.getEngine();
232 SpreadsheetEngine engine = book.getEngine(sheetName);
233 if(engine == null) return null;
235 Range r = Spreadsheets.decodeCellAbsolute(cellName);
236 SpreadsheetLine line = engine.getLine(r.startRow);
237 if(line == null) return null;
239 String path = line.getPath();
240 if(path == null) return null;
242 Variable lineVariable = run.browse(graph, path);
243 if(lineVariable==null) return null;
245 return lineVariable.getChild(graph, cellName);
249 public static void forRows(ReadGraph graph, Variable run, String sheetName, int min, int max, Function1<Variable, Tuple> fn) throws DatabaseException {
251 String sessionName = run.getParent(graph).getURI(graph);
252 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
253 SpreadsheetBook book = realm.getEngine();
254 SpreadsheetEngine engine = book.getEngine(sheetName);
255 if(engine == null) return;
257 engine.forLines(line -> {
259 String path = line.getPath();
260 if(path == null) return;
263 Variable lineVariable = run.browse(graph, path);
264 if(lineVariable != null)
265 fn.apply(lineVariable);
266 } catch (DatabaseException e) {
267 // This is not reported here
274 public static List<Variable> possibleConfigurationCellVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
275 List<Variable> rowVariables = possibleConfigurationLineVariables(graph, sheet, range);
276 List<Variable> result = new ArrayList<>();
277 for (Variable variable : rowVariables) {
278 Collection<Variable> children = variable.getChildren(graph);
279 for (Variable child : children) {
280 if (variableInRange(graph, child, range)) {
288 public static Map<Integer, Resource> possibleConfigurationLineResources(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
289 Variable lines = sheet.getPossibleChild(graph, "Lines");
291 throw new DatabaseException("Invalid input variable " + sheet.getURI(graph));
292 Resource linesR = lines.getRepresents(graph);
293 BTree bt = new BTree(graph, linesR);
294 List<Tuple2> tuples = bt.searchRangeBTree(graph, Variant.ofInstance(range.startRow), Variant.ofInstance(range.endRow));
295 Map<Integer, Resource> result = new HashMap<>(tuples.size());
296 for (Tuple2 tuple : tuples) {
297 Integer lineNumber = (Integer)((Variant)tuple.c0).getValue();
298 Resource resource = (Resource)tuple.c1;
299 result.put(lineNumber, resource);
304 public static List<Variable> possibleConfigurationLineVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
305 Map<Integer, Resource> rows = possibleConfigurationLineResources(graph, sheet, range);
306 List<Variable> result = new ArrayList<>(rows.size());
307 for (Resource row: rows.values()) {
308 Variable lineVar = Variables.getPossibleVariable(graph, row);
315 public static List<Variable> possibleRunLineVariables(ReadGraph graph, Variable sheetRun, Range range) throws DatabaseException {
317 Variable run = sheetRun.getParent(graph);
319 String sheetName = sheetRun.getName(graph);
320 String sessionName = run.getParent(graph).getURI(graph);
322 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
323 SpreadsheetBook book = realm.getEngine();
325 SpreadsheetEngine engine = book.getEngine(sheetName);
326 if(engine == null) return null;
328 List<Variable> result = new ArrayList<>();
330 int end = range.endRow < engine.lines.getMaxRow() ? range.endRow : engine.lines.getMaxRow();
331 for (int i = range.startRow; i <= end; i++) {
332 SpreadsheetLine line = engine.getLine(i);
336 String path = line.getPath();
337 path = line.getPath();
341 Variable lineVariable = run.browse(graph, path);
342 if(lineVariable==null)
344 result.add(lineVariable);
350 public static List<Variable> possibleRunCellVariables(ReadGraph graph, Variable sheetRun, Range range) throws DatabaseException {
351 List<Variable> runLineVariable = possibleRunLineVariables(graph, sheetRun, range);
352 List<Variable> result = new ArrayList<>();
353 for (Variable variable : runLineVariable) {
354 // System.out.println("line: " + variable.getURI(graph));
355 for (Variable child : variable.getChildren(graph)) {
356 // System.out.print("cell : " + child.getURI(graph));
357 if (variableInRange(graph, child, range)) {
365 private static boolean variableInRange(ReadGraph graph, Variable child, Range range) throws DatabaseException {
366 String name = child.getName(graph);
367 Range childRange = Spreadsheets.decodeCellAbsolute(name);
368 // System.out.print(" and range " + childRange);
369 if (childRange != null && range.contains(childRange)) {
370 // System.out.println(" => range.contains(childRange) = true");
373 // System.out.println();
377 public static Map<Integer, Resource> createConfigurationLineResources(WriteGraph graph, Variable sheet, Range range) throws DatabaseException {
378 Layer0 L0 = Layer0.getInstance(graph);
379 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
381 Variable lines = sheet.getPossibleChild(graph, "Lines");
383 throw new DatabaseException("Invalid input variable " + sheet.getURI(graph));
384 Resource linesR = lines.getRepresents(graph);
385 BTree bt = new BTree(graph, linesR);
387 Map<Integer, Resource> result = new HashMap<>();
388 for (int lineNumber = range.startRow; lineNumber <= range.endRow; lineNumber++) {
389 Resource line = graph.newResource();
390 graph.claim(line, L0.InstanceOf, null, SHEET.Line);
391 graph.claimLiteral(line, L0.HasName, L0.NameOf, L0.String, "Row" + lineNumber, Bindings.STRING);
392 bt.insertBTree(graph, Variant.ofInstance(lineNumber), line);
393 result.put(lineNumber, line);
398 public static List<Variable> getOrCreateConfigurationCellVariables(WriteGraph graph, Variable sheet, Range range) throws DatabaseException {
400 List<Variable> rows = possibleConfigurationLineVariables(graph, sheet, range);
401 if (rows.isEmpty()) {
402 createConfigurationLineResources(graph, sheet, range);
403 rows = possibleConfigurationLineVariables(graph, sheet, range);
406 List<Variable> cells = possibleConfigurationCellVariables(graph, sheet, range);
407 if (cells.isEmpty()) {
408 Iterator<Variable> rowIterator = rows.iterator();
409 for (int rowNumber = range.startRow; rowNumber <= range.endRow; rowNumber++) {
410 Variable row = rowIterator.next();
411 for (int colNumber = range.startColumn; colNumber <= range.endColumn; colNumber++) {
412 String location = Spreadsheets.cellName(rowNumber, colNumber);
413 defaultCreateCell(graph, row, location, new Variant(Bindings.STRING, ""));
418 cells = possibleConfigurationCellVariables(graph, sheet, range);
420 throw new DatabaseException("Unexpected problem while creating spreadsheet cell at '" + range + "'");
425 private static void defaultCreateCell(WriteGraph graph, Variable parent, String location, Variant value) throws DatabaseException {
427 Layer0 L0 = Layer0.getInstance(graph);
428 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
429 Resource container = parent.getRepresents(graph);
431 Resource cell = graph.newResource();
432 graph.claim(cell, L0.InstanceOf, null, SHEET.TextCell);
433 graph.addLiteral(cell, L0.HasName, L0.NameOf, L0.String, location, Bindings.STRING);
434 graph.addLiteral(cell, SHEET.Cell_content, SHEET.Cell_content_Inverse, L0.Variant, value, Bindings.VARIANT);
435 graph.claim(cell, L0.PartOf, container);
437 Resource book = Variables.getContext(graph, parent).getRepresents(graph);
440 Collection<Resource> objects = graph.sync(new ObjectsWithType(book, L0.ConsistsOf, SHEET.Style));
442 int styleId = SpreadsheetStyle.empty().getStyleId();
443 Resource style = null;
444 for (Resource possibleStyle : objects) {
445 int possibleStyleId = graph.getRelatedValue2(possibleStyle, SHEET.Style_id, Bindings.INTEGER);
446 if (possibleStyleId == styleId) {
447 style = possibleStyle;
453 style = graph.newResource();
454 graph.claim(style, L0.InstanceOf, null, SHEET.Style);
455 graph.claim(style, L0.PartOf, book);
457 int id = objects.size();
458 graph.claimLiteral(style, L0.HasName, "Style_" + id);
459 graph.claimLiteral(style, SHEET.Style_id, styleId, Bindings.INTEGER);
461 graph.claim(cell, SHEET.Cell_HasStyle, style);
462 Layer0Utils.addCommentMetadata(graph, "Created cell on location " + location + " with value " + value.toString());
465 public static Resource createStyle(WriteGraph graph, Resource book, SpreadsheetStyle sstyle) throws DatabaseException {
466 Layer0 L0 = Layer0.getInstance(graph);
467 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
468 Resource style = graph.newResource();
469 graph.claim(style, L0.InstanceOf, null, SR.Style);
470 graph.claim(style, L0.PartOf, book);
472 int styleId = sstyle.getStyleId();
473 String styleName = sstyle.name;
475 graph.claimLiteral(style, L0.HasName, styleName);
476 //System.err.println("CREATING STYLE " + styleName + " WITH ID: " + styleId);
477 graph.claimLiteral(style, SR.Style_id, styleId, Bindings.INTEGER);
479 DatatypeResource DATATYPES = DatatypeResource.getInstance(graph);
480 if (sstyle.foreground != null)
481 graph.claimLiteral(style, SR.Cell_foreground, DATATYPES.RGB_Integer, sstyle.foreground, RGB.Integer.BINDING);
482 if (sstyle.background != null)
483 graph.claimLiteral(style, SR.Cell_background, DATATYPES.RGB_Integer, sstyle.background, RGB.Integer.BINDING);
484 if (sstyle.align != -1)
485 graph.claimLiteral(style, SR.Cell_align, sstyle.align, Bindings.INTEGER);
486 if (sstyle.font != null)
487 graph.claimLiteral(style, SR.Cell_font, DATATYPES.Font, sstyle.font, Font.BINDING);
488 if (sstyle.border != -1)
489 graph.claimLiteral(style, SR.Cell_border, sstyle.border);
490 if (sstyle.formatString != null && !sstyle.formatString.isEmpty())
491 graph.claimLiteral(style, SR.Cell_formatString, sstyle.formatString, Bindings.STRING);
492 if (sstyle.formatIndex != -1)
493 graph.claimLiteral(style, SR.Cell_formatIndex, sstyle.formatIndex, Bindings.INTEGER);
498 public static Resource createBook(WriteGraph graph, Resource parent, String name) throws DatabaseException {
499 Layer0 L0 = Layer0.getInstance(graph);
500 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
501 Resource book = graph.newResource();
502 graph.claim(book, L0.InstanceOf, SR.Book);
503 graph.claimLiteral(book, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING);
504 graph.claim(parent, L0.ConsistsOf, book);
509 public static Variable constructAndInitializeRunVariable(WriteGraph graph, Resource root) throws DatabaseException {
510 Variable run = SpreadsheetUtils.getBookVariable(graph, root);
511 SpreadsheetGraphUtils.fullSynchronization(graph, run);
512 SpreadsheetGraphUtils.evaluateAll(graph, run);
513 SpreadsheetGraphUtils.saveInitialCondition(graph, run, root, "Initial");
517 public static Variant extRefVariable(ReadGraph graph, Variable var) throws DatabaseException {
518 return new Variant(Bindings.VOID, new ExternalRefVariable(graph, var));
521 static class ExternalRefVariable implements ExternalRef {
523 final private String uri;
525 public ExternalRefVariable(ReadGraph graph, Variable variable) throws DatabaseException {
526 this.uri = variable.getURI(graph);
530 public void listen(Object context, ExternalRefListener listener) {
531 Simantics.getSession().asyncRequest(new UnaryRead<String, Variant>(uri) {
534 public Variant perform(ReadGraph graph) throws DatabaseException {
535 Variable variable = Variables.getVariable(graph, parameter);
536 return variable.getVariantValue(graph);
539 }, new Listener<Variant>() {
542 public void execute(Variant result) {
543 listener.newValue(result);
547 public void exception(Throwable t) {
548 LOGGER.error("Error while evaluating variable value", t);
552 public boolean isDisposed() {
553 return listener.isDisposed();
560 public void modify(Object context, Variant newValue) {
562 Simantics.getSession().asyncRequest(new WriteRequest() {
565 public void perform(WriteGraph graph) throws DatabaseException {
566 Variable variable = Variables.getVariable(graph, uri);
567 variable.setValue(graph, newValue);
575 public static Variant extRefActiveVariable(ReadGraph graph, Variable var) throws DatabaseException {
576 return new Variant(Bindings.VOID, new ExternalRefActiveVariable(graph, var));
579 static class ExternalRefActiveVariable implements ExternalRef {
581 final private String uri;
583 public ExternalRefActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {
584 this.uri = variable.getURI(graph);
588 public void listen(Object context, ExternalRefListener listener) {
589 Simantics.getSession().asyncRequest(new BinaryRead<String, String, Variant>((String)context, uri) {
592 public Variant perform(ReadGraph graph) throws DatabaseException {
593 Variable contextVariable = Variables.getVariable(graph, parameter);
594 Variable configVariable = Variables.getVariable(graph, parameter2);
595 Variable activeVariable = Variables.switchPossibleContext(graph, configVariable, contextVariable.getRepresents(graph));
596 if(activeVariable == null) return Variant.ofInstance("Could not resolve " + configVariable.getURI(graph) + " for " + contextVariable.getURI(graph));
597 return activeVariable.getVariantValue(graph);
599 }, new Listener<Variant>() {
602 public void execute(Variant result) {
603 listener.newValue(result);
607 public void exception(Throwable t) {
608 LOGGER.error("Error while evaluating variable value, context = " + context + " uri=" + uri, t);
612 public boolean isDisposed() {
613 return listener.isDisposed();
620 public void modify(Object context, Variant newValue) {
622 Simantics.getSession().asyncRequest(new WriteRequest() {
625 public void perform(WriteGraph graph) throws DatabaseException {
626 Variable contextVariable = Variables.getVariable(graph, (String)context);
627 Variable configVariable = Variables.getVariable(graph,uri);
628 Variable activeVariable = Variables.switchPossibleContext(graph, configVariable, contextVariable.getRepresents(graph));
629 if(activeVariable == null) return;
630 activeVariable.setValue(graph, newValue.getValue(), newValue.getBinding());
638 public static CellEditor cellEditor(ReadGraph graph, Resource sheet) throws DatabaseException {
639 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
640 Variable sheetVariable = Variables.getVariable(graph, sheet);
641 return sheetVariable.getPropertyValue(graph, SHEET.cellEditor);
644 public static final String SPREADSHEET_TRANSACTION = "spreadsheetTransaction";
646 @SuppressWarnings({ "rawtypes", "unchecked" })
647 public static Object syncExec(CellEditor editor, OperationMode mode, Function fun) throws InterruptedException {
649 Transaction tr = editor.startTransaction(mode);
651 SCLContext context = SCLContext.getCurrent();
652 Transaction oldTransaction = (Transaction)context.put(SPREADSHEET_TRANSACTION, tr);
654 Object result = null;
658 result = fun.apply(Tuple0.INSTANCE);
664 context.put(SPREADSHEET_TRANSACTION, oldTransaction);
672 public static int cellColumn(ReadGraph graph, Variable cell) {
673 if(cell instanceof StandardGraphChildVariable) {
674 StandardGraphChildVariable sgcv = (StandardGraphChildVariable)cell;
675 SpreadsheetCell sc = (SpreadsheetCell)sgcv.node.node;
676 return sc.getColumn();
678 throw new IllegalStateException("Expected StandardGraphChildVariable, got " + cell.getClass().getName());
681 private static SpreadsheetCell getCellFromVariable(Variable cell) {
682 StandardGraphChildVariable std = (StandardGraphChildVariable)cell;
683 return (SpreadsheetCell)std.node.node;
686 private static SpreadsheetLine getLineFromVariable(Variable cell) {
687 StandardGraphChildVariable std = (StandardGraphChildVariable)cell;
688 return (SpreadsheetLine)std.node.node;
691 public static Variable linesVariable(ReadGraph graph, Variable sheetVariable) throws DatabaseException {
692 while(!"Lines".equals(sheetVariable.getName(graph)))
693 sheetVariable = sheetVariable.getParent(graph);
694 return sheetVariable;
697 public static Variable offsetCell(ReadGraph graph, Variable cellVariable, int x, int y) throws DatabaseException {
699 Variable lineVariable = cellVariable.getParent(graph);
700 Variable offsetLine = offsetRow(graph, lineVariable, y);
701 if(offsetLine == null) return null;
702 SpreadsheetCell cell = getCellFromVariable(cellVariable);
703 return rowCell(graph, offsetLine, cell.column + x);
707 public static Variable offsetRow(ReadGraph graph, Variable lineVariable, int offset) throws DatabaseException {
709 if(offset == 0) return lineVariable;
711 SpreadsheetLine line = getLineFromVariable(lineVariable);
712 SpreadsheetLine offsetLine = line.possibleOffset(offset);
713 if(offsetLine == null) return null;
715 Variable linesVariable = linesVariable(graph, lineVariable);
716 String path = offsetLine.getLinesPath();
717 return linesVariable.browsePossible(graph, path);
721 public static Variable rowCell(ReadGraph graph, Variable lineVariable, int column) throws DatabaseException {
723 SpreadsheetLine line = getLineFromVariable(lineVariable);
725 return lineVariable.getPossibleChild(graph, Spreadsheets.cellName(line.row, column));
729 public static SpreadsheetBook spreadsheetBook(Variable variable) {
730 if(variable instanceof StandardGraphChildVariable) {
731 VariableNode<Node> node = ((StandardGraphChildVariable)variable).node;
733 if(node.node instanceof SpreadsheetBook)
734 return (SpreadsheetBook) node.node;