1 package org.simantics.spreadsheet.graph.function;
3 import java.io.StringReader;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.HashSet;
12 import java.util.function.Consumer;
14 import org.simantics.databoard.Bindings;
15 import org.simantics.databoard.Databoard;
16 import org.simantics.databoard.adapter.AdaptException;
17 import org.simantics.databoard.binding.Binding;
18 import org.simantics.databoard.binding.mutable.MutableVariant;
19 import org.simantics.databoard.binding.mutable.Variant;
20 import org.simantics.databoard.type.Datatype;
21 import org.simantics.datatypes.literal.Font;
22 import org.simantics.datatypes.literal.RGB;
23 import org.simantics.datatypes.utils.BTreeContentBean;
24 import org.simantics.db.ReadGraph;
25 import org.simantics.db.Resource;
26 import org.simantics.db.WriteGraph;
27 import org.simantics.db.common.request.ObjectsWithType;
28 import org.simantics.db.common.request.WriteRequest;
29 import org.simantics.db.common.utils.Logger;
30 import org.simantics.db.common.utils.NameUtils;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.db.layer0.exception.MissingVariableException;
33 import org.simantics.db.layer0.function.StandardChildDomainChildren;
34 import org.simantics.db.layer0.request.PossibleActiveRun;
35 import org.simantics.db.layer0.util.Layer0Utils;
36 import org.simantics.db.layer0.variable.ConstantChildVariable;
37 import org.simantics.db.layer0.variable.ConstantPropertyVariableBuilder;
38 import org.simantics.db.layer0.variable.ProxyChildVariable;
39 import org.simantics.db.layer0.variable.ProxyVariables;
40 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
41 import org.simantics.db.layer0.variable.ValueAccessor;
42 import org.simantics.db.layer0.variable.Variable;
43 import org.simantics.db.layer0.variable.VariableMap;
44 import org.simantics.db.layer0.variable.VariableMapImpl;
45 import org.simantics.db.layer0.variable.Variables;
46 import org.simantics.db.request.Write;
47 import org.simantics.document.server.io.IColor;
48 import org.simantics.document.server.io.IFont;
49 import org.simantics.document.server.io.ITableCell;
50 import org.simantics.layer0.Layer0;
51 import org.simantics.scl.reflection.annotations.SCLValue;
52 import org.simantics.simulator.toolkit.StandardRealm;
53 import org.simantics.simulator.variable.exceptions.NodeManagerException;
54 import org.simantics.spreadsheet.CellEditor;
55 import org.simantics.spreadsheet.ClientModel;
56 import org.simantics.spreadsheet.Range;
57 import org.simantics.spreadsheet.Spreadsheets;
58 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
59 import org.simantics.spreadsheet.graph.SpreadsheetNodeManager;
60 import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
61 import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
62 import org.simantics.spreadsheet.resource.SpreadsheetResource;
63 import org.simantics.spreadsheet.solver.SheetNode;
64 import org.simantics.spreadsheet.solver.SpreadsheetBook;
65 import org.simantics.spreadsheet.solver.SpreadsheetCell;
66 import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
67 import org.simantics.spreadsheet.solver.SpreadsheetFormula;
68 import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
69 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
70 import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
71 import org.simantics.spreadsheet.solver.formula.parser.ParseException;
72 import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
73 import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
74 import org.simantics.spreadsheet.synchronization.ExcelFormula;
75 import org.simantics.spreadsheet.synchronization.LineContentBean;
76 import org.simantics.spreadsheet.synchronization.LineContentBeanCell;
77 import org.simantics.spreadsheet.util.SpreadsheetUtils;
79 import gnu.trove.map.TMap;
80 import gnu.trove.map.hash.THashMap;
81 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
85 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
86 public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
87 if(context instanceof Resource) {
88 return NameUtils.getSafeLabel(graph, ((Resource)context));
89 } else if (context instanceof Variable) {
90 Variable parent = ((Variable)context).getParent(graph);
91 Variable content = parent.getPossibleProperty(graph, ClientModel.CONTENT);
93 Databoard db = graph.getService(Databoard.class);
94 Variant variant = content.getValue(graph, db.VARIANT);
95 return variant.getValue().toString();
97 return parent.getName(graph);
100 throw new DatabaseException("Unknown context " + context);
104 private static Set<String> CLASSIFICATIONS = new HashSet<String>();
105 private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN);
108 CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
111 @SCLValue(type = "ValueAccessor")
112 public static ValueAccessor contentValueAccessor = new ValueAccessor() {
115 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
116 if(value instanceof String) {
118 // Expressions are given as string
119 String text = (String)value;
120 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
121 if (text.startsWith("==")) {
123 if(ProxyVariables.isProxy(graph, context))
124 // SCL expressions are not supported in solver
127 if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
128 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
129 //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
130 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
135 Variable cell = context.getParent(graph);
137 String formula = text.substring(1);
139 if (ProxyVariables.isProxy(graph, context)) {
141 SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
142 AstValue v = p.relation();
143 SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
144 setValueToEngine(graph, cell, context, sformula, SpreadsheetFormula.BINDING);
145 } catch (ParseException e) {
152 Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
153 Layer0Utils.claimLiteral(graph, cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
158 if(ProxyVariables.isProxy(graph, context)) {
160 Variable cell = context.getParent(graph);
161 setValueToEngine(graph, cell, context, value, binding);
165 // Values are given as Variant
166 String expression = context.getPossiblePropertyValue(graph, "expression");
167 if(expression != null) {
168 Object current_ = context.getPossibleValue(graph);
169 if(current_ instanceof Variable) {
170 Variable current = (Variable)current_;
171 Variant variant = (Variant)value;
172 Datatype dt = current.getDatatype(graph);
174 throw new DatabaseException();
176 Binding variableBinding = Bindings.getBinding(dt);
178 Object adapted = variant.getValue(variableBinding);
179 current.setValue(graph, adapted, variableBinding);
180 } catch (AdaptException e) {
181 Logger.defaultLogError(e);
185 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
186 Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
188 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
189 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
193 private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
194 Variable sheet = cell.getParent(graph);
196 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
198 while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
199 sheet = sheet.getParent(graph);
202 Range r = Spreadsheets.decodeCellAbsolute(cell.getName(graph));
204 Variable root = ProxyVariables.proxyVariableRoot(graph, context);
206 String sessionName = root.getParent(graph).getURI(graph);
207 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
208 SpreadsheetBook book = realm.getEngine();
209 SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
210 sc.setContent(value);
211 realm.asyncExec(new Runnable() {
216 SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
217 realm.getNodeManager().setValue(content, value, binding);
218 } catch (NodeManagerException e) {
219 Logger.defaultLogError(e);
226 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
227 if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
228 else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
229 else throw new DatabaseException("Unsupported value type " + value);
233 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
234 return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
235 //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
239 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
240 return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
241 // return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
245 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
246 return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
247 // return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
252 @SCLValue(type = "ValueAccessor")
253 public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
256 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
257 if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
258 if (!(value instanceof String)) throw new IllegalArgumentException();
260 if (((String)value).startsWith("=")) {
261 context.getParent(graph).setValue(graph, value, Bindings.STRING);
263 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
268 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
269 if (!(value instanceof String)) throw new IllegalArgumentException();
271 if (((String)value).startsWith("=")) {
272 context.getParent(graph).setValue(graph, value, Bindings.STRING);
274 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
279 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
280 return context.getParent(graph).getValue(graph, binding);
284 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
285 return context.getParent(graph).getValue(graph);
289 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
290 return context.getParent(graph).getDatatype(graph);
295 @SCLValue(type = "VariableMap")
296 public static VariableMap stringArrayChildren = new VariableMapImpl() {
299 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
301 TMap<String, Variable> map = new THashMap<String, Variable>();
302 getVariables(graph, context, map);
303 return map.get(name);
308 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
310 Resource resource = context.getRepresents(graph);
312 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
314 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
315 if(location == null) return map;
316 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
317 if(width == null) return map;
318 String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
319 if(array == null) return map;
321 int rows = array.length / width;
323 if(map == null) map = new HashMap<String,Variable>();
325 for(int offset=0,i=0;i<rows;i++) {
326 for(int j=0;j<width;j++) {
328 String value = array[offset++];
329 String valueLocation = Spreadsheets.offset(location, i, j);
331 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
332 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
334 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
345 @SCLValue(type = "VariableMap")
346 public static VariableMap queryRangeChildren = new VariableMapImpl() {
349 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
351 TMap<String, Variable> map = new THashMap<String, Variable>();
352 getVariables(graph, context, map);
353 return map.get(name);
358 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
360 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
362 String location = "A1";
366 Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
368 List<?> data = (List<?>)object;
370 if(map == null) map = new HashMap<String,Variable>();
372 for(Object o : data) {
373 if(o instanceof ITableCell) {
375 ITableCell cell = (ITableCell)o;
377 String valueLocation = Spreadsheets.offset(location, cell.getRow(), cell.getColumn());
379 ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
381 builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
382 builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
384 IFont font = cell.getFont();
386 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
389 int align = cell.getAlign();
390 builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
392 IColor foreground = cell.getFGColor();
393 if(foreground != null) {
394 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
397 IColor background = cell.getBGColor();
398 if(background != null) {
399 builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
402 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
407 } catch (DatabaseException e) {
408 throw (DatabaseException)e;
409 } catch (Throwable t) {
410 throw new DatabaseException(t);
420 @SCLValue(type = "VariableMap")
421 public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
424 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
426 if(ProxyVariables.isProxy(graph, context))
427 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
429 return super.getVariable(graph, context, name);
434 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
436 if(ProxyVariables.isProxy(graph, context))
437 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);
439 return super.getVariables(graph, context, map);
445 @SCLValue(type = "VariableMap")
446 public static VariableMap doubleArrayChildren = new VariableMapImpl() {
449 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
451 TMap<String, Variable> map = new THashMap<String, Variable>();
452 getVariables(graph, context, map);
453 return map.get(name);
458 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
460 Resource resource = context.getRepresents(graph);
462 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
464 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
465 if(location == null) return map;
466 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
467 if(width == null) return map;
468 double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
469 if(array == null) return map;
471 if(map == null) map = new HashMap<String,Variable>();
473 int rows = array.length / width;
475 for(int offset=0,i=0;i<rows;i++) {
476 for(int j=0;j<width;j++) {
478 double value = array[offset++];
479 String valueLocation = Spreadsheets.offset(location, i, j);
481 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
482 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
484 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
495 static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
497 public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
498 super(base, parent, other, name);
502 public Variable create(Variable base, Variable parent, Variable other, String name) {
503 return new SpreadsheetProxyChildVariable(base, parent, other, name);
506 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
508 if(CONTEXT_END.equals(name)) {
509 if(other instanceof ProxyChildVariable) {
510 // The context is also a proxy - let it do the job
511 return super.getPossibleChild(graph, name);
513 return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
517 return super.getPossibleChild(graph, name);
521 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
523 Collection<Variable> result = super.getChildren(graph);
524 if(!(base instanceof ProxyChildVariable)) {
525 Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
534 @SCLValue(type = "VariableMap")
535 public static VariableMap spreadsheetChildren = new VariableMapImpl() {
538 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
540 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
541 return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
545 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
546 Variable root = Variables.getRootVariable(graph);
547 return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
552 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
553 throws DatabaseException {
555 map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
557 if(map == null) map = new HashMap<String,Variable>();
558 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
565 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
566 public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
568 final Variable sheet = context_.getParent(graph);
570 return new GraphCellEditorAdapter(null) {
573 public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
575 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
578 public void perform(WriteGraph graph) throws DatabaseException {
579 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
582 editor.edit(transaction, location, property, value, binding, callback);
589 public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
590 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
593 public void perform(WriteGraph graph) throws DatabaseException {
594 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
597 editor.edit(transaction, location, value, callback);
603 private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
604 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
605 Range range = Spreadsheets.decodePossibleCellAbsolute(location);
606 if(range == null) return null; //No editor found
608 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
609 if (cells.isEmpty()) {
613 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
616 if (cells.size() != 1)
617 throw new DatabaseException("Can edit only one cell at a time!");
619 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
623 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
625 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
628 public void perform(WriteGraph graph) throws DatabaseException {
630 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
631 Variable variable = sheet.getPossibleChild(graph, location);
632 if(variable != null) {
633 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
635 editor.copy(transaction, location, variant, null);
648 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
649 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
651 final Variable cell = context_.getParent(graph);
653 return new GraphCellEditorAdapter(cell) {
656 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
657 cell.setPropertyValue(graph, property, value, binding);
662 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
663 if(r == null) return 0;
664 Layer0 L0 = Layer0.getInstance(graph);
665 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
666 if(name.charAt(0) == 'R') {
667 return -Integer.parseInt(name.substring(3));
669 return Integer.parseInt(name);
673 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
674 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
676 Resource node = context_.getParent(graph).getRepresents(graph);
677 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
678 if(bean == null) return new int[0];
679 // There are n keys and n+1 resources
680 int[] result = new int[2*bean.n+1];
681 for(int i=0;i<bean.n;i++) {
682 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
683 result[2*i+1] = (int)bean.getKey(i).getValue();
685 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
690 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
691 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
693 String contextUri = context_.getURI(graph);
695 Variable line = context_.getParent(graph);
697 Collection<Variable> children = line.getChildren(graph);
698 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
699 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
700 for (Variable child : children) {
701 Resource repr = child.getRepresents(graph);
703 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
704 Integer styleId = null;
706 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
707 if (styleId == null) {
708 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
709 styleId = SpreadsheetStyle.empty().getStyleId();
712 LineContentBeanCell cell = new LineContentBeanCell(styleId);
714 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
716 if(variant != null) {
718 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
719 String expression = var.getPossiblePropertyValue(graph, "expression");
720 if (expression != null) {
721 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
723 cell.setContent(variant);
725 Range r = Spreadsheets.decodeCellAbsolute(child.getName(graph));
727 while(result.size() < r.startColumn + 1)
728 result.add(new LineContentBeanCell());
729 result.set(r.startColumn, cell);
734 LineContentBean bean = new LineContentBean();
735 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
740 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
741 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
743 Variable cells = context_.getParent(graph);
745 return new GraphCellEditorAdapter(cells) {
747 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
749 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
750 if(ClientModel.CONTENT.equals(property)) {
751 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
752 Variable runCell = null;
753 Object transactionContext = transaction.getContext();
754 if (transactionContext != null && transactionContext instanceof Variable) {
755 Variable varContext = (Variable) transactionContext;
756 Variable context = Variables.getContext(graph, varContext);
758 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
759 } catch (MissingVariableException e) {
760 // Creating new cell, need synchronizing
761 transaction.needSynchronization(cell.getParent(graph));
765 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
766 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
767 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
768 Variable runCell = null;
769 Object transactionContext = transaction.getContext();
770 if (transactionContext != null && transactionContext instanceof Variable) {
771 Variable varContext = (Variable) transactionContext;
772 Variable context = Variables.getContext(graph, varContext);
774 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
775 } catch (MissingVariableException e) {
776 //Creating new cell, need synchronizing
777 transaction.needSynchronization(cell.getParent(graph));
781 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
782 // SCL expressions always require synchronization
783 if(value.toString().startsWith("=="))
784 transaction.needSynchronization(cell.getParent(graph));
785 } else if(ClientModel.BORDER.equals(property)) {
786 Resource textCell = cell.getRepresents(graph);
787 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
788 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
789 builder.border((Integer)value);
790 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
791 } else if(ClientModel.ALIGN.equals(property)) {
792 Resource textCell = cell.getRepresents(graph);
793 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
794 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
795 builder.align((Integer)value);
796 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
797 } else if(ClientModel.LOCKED.equals(property)) {
798 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
799 } else if(ClientModel.ROW_SPAN.equals(property)) {
800 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
801 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
802 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
803 } else if(ClientModel.FONT.equals(property)) {
804 Resource textCell = cell.getRepresents(graph);
805 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
806 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
807 builder.font((Font)value);
808 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
809 } else if(ClientModel.FOREGROUND.equals(property)) {
810 Resource textCell = cell.getRepresents(graph);
811 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
812 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
813 builder.foreground((RGB.Integer)value);
814 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
815 } else if(ClientModel.BACKGROUND.equals(property)) {
816 Resource textCell = cell.getRepresents(graph);
817 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
818 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
819 builder.background((RGB.Integer)value);
820 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
824 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
826 Variable bookVariable = Variables.getContext(graph, cell);
827 Resource book = bookVariable.getRepresents(graph);
828 Resource createdStyle = null;
830 SpreadsheetStyle style = builder.build();
831 int styleId = style.getStyleId();
833 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
834 for (Resource eStyle : existingStyles) {
835 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
836 if (eStyleId == styleId) {
837 createdStyle = eStyle;
841 if (createdStyle == null) {
842 style = builder.name("Style_" + existingStyles.size()).build();
843 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
846 graph.deny(textCell, SHEET.Cell_HasStyle);
847 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
848 if (cellsOfStyle.isEmpty()) {
849 graph.deny(styleContainer);
851 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
855 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
856 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
857 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
858 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
859 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
860 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
862 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
866 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
867 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
869 // Handle possible deletes
871 value = Variant.ofInstance("");
873 if (!transaction.isOperationMode()) {
874 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
877 Variable runCell = null;
878 Object transactionContext = transaction.getContext();
879 if (transactionContext != null && transactionContext instanceof Variable) {
880 Variable varContext = (Variable) transactionContext;
881 Variable context = Variables.getContext(graph, varContext);
883 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
884 } catch (MissingVariableException e) {
885 // Creating cell for the first time so no runCell available at this time, needs synchronization
886 transaction.needSynchronization(cell.getParent(graph));
891 if (runCell != null) {
892 System.out.println("All.edit " + runCell.getURI(graph));
893 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
898 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
899 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
901 Variable runCell = null;
902 Object transactionContext = transaction.getContext();
903 if (transactionContext != null && transactionContext instanceof Variable) {
904 Variable varContext = (Variable) transactionContext;
905 Variable context = Variables.getContext(graph, varContext);
906 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
909 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
910 Variant content = null;
911 if (object instanceof Variant) {
912 content = (Variant)object;
913 } else if (object instanceof Double) {
914 content = Variant.ofInstance((Double)object);
915 } else if (object instanceof Float) {
916 content = Variant.ofInstance((Float)object);
917 } else if (object instanceof Integer) {
918 content = Variant.ofInstance((Integer)object);
919 } else if (object instanceof Long) {
920 content = Variant.ofInstance((Long)object);
921 } else if (object instanceof String) {
922 content = Variant.ofInstance((String)object);
923 } else if (object instanceof Variable) {
924 content = Variant.ofInstance((Variable)object);
926 throw new DatabaseException("");
928 variant.setValue(content);
935 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
936 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
937 return ProxyVariables.inputVariable(graph, sheet);
940 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
941 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
942 return ProxyVariables.proxySessionVariable(graph, sheet);
945 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
946 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
947 Resource model = Variables.getModel(graph, property);
948 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
949 if(activeRun != null) return activeRun;
950 return Variables.getConfigurationContext(graph, model);
953 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
954 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
955 return CompileSCLValueRequest.compileAndEvaluate(graph, context);