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.Transaction;
59 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
60 import org.simantics.spreadsheet.graph.SpreadsheetNodeManager;
61 import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
62 import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
63 import org.simantics.spreadsheet.resource.SpreadsheetResource;
64 import org.simantics.spreadsheet.solver.SheetNode;
65 import org.simantics.spreadsheet.solver.SpreadsheetBook;
66 import org.simantics.spreadsheet.solver.SpreadsheetCell;
67 import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
68 import org.simantics.spreadsheet.solver.SpreadsheetFormula;
69 import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
70 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
71 import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
72 import org.simantics.spreadsheet.solver.formula.parser.ParseException;
73 import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
74 import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
75 import org.simantics.spreadsheet.synchronization.ExcelFormula;
76 import org.simantics.spreadsheet.synchronization.LineContentBean;
77 import org.simantics.spreadsheet.synchronization.LineContentBeanCell;
78 import org.simantics.spreadsheet.util.SpreadsheetUtils;
80 import gnu.trove.map.TMap;
81 import gnu.trove.map.hash.THashMap;
82 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
86 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
87 public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
88 if(context instanceof Resource) {
89 return NameUtils.getSafeLabel(graph, ((Resource)context));
90 } else if (context instanceof Variable) {
91 Variable parent = ((Variable)context).getParent(graph);
92 Variable content = parent.getPossibleProperty(graph, ClientModel.CONTENT);
94 Databoard db = graph.getService(Databoard.class);
95 Variant variant = content.getValue(graph, db.VARIANT);
96 return variant.getValue().toString();
98 return parent.getName(graph);
101 throw new DatabaseException("Unknown context " + context);
105 private static Set<String> CLASSIFICATIONS = new HashSet<String>();
106 private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN);
109 CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
112 @SCLValue(type = "ValueAccessor")
113 public static ValueAccessor contentValueAccessor = new ValueAccessor() {
116 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
117 if(value instanceof String) {
119 // Expressions are given as string
120 String text = (String)value;
121 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
122 if (text.startsWith("==")) {
124 if(ProxyVariables.isProxy(graph, context))
125 // SCL expressions are not supported in solver
128 if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
129 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
130 //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
131 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
136 Variable cell = context.getParent(graph);
138 String formula = text.substring(1);
140 if (ProxyVariables.isProxy(graph, context)) {
142 SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
143 AstValue v = p.relation();
144 SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
145 setValueToEngine(graph, cell, context, sformula, SpreadsheetFormula.BINDING);
146 } catch (ParseException e) {
153 Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
154 Layer0Utils.claimLiteral(graph, cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
159 if(ProxyVariables.isProxy(graph, context)) {
161 Variable cell = context.getParent(graph);
162 setValueToEngine(graph, cell, context, value, binding);
166 // Values are given as Variant
167 String expression = context.getPossiblePropertyValue(graph, "expression");
168 if(expression != null) {
169 Object current_ = context.getPossibleValue(graph);
170 if(current_ instanceof Variable) {
171 Variable current = (Variable)current_;
172 Variant variant = (Variant)value;
173 Datatype dt = current.getDatatype(graph);
175 throw new DatabaseException();
177 Binding variableBinding = Bindings.getBinding(dt);
179 Object adapted = variant.getValue(variableBinding);
180 current.setValue(graph, adapted, variableBinding);
181 } catch (AdaptException e) {
182 Logger.defaultLogError(e);
186 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
187 Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
189 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
190 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
194 private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
195 Variable sheet = cell.getParent(graph);
197 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
199 while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
200 sheet = sheet.getParent(graph);
203 Range r = Spreadsheets.decodeCellAbsolute(cell.getName(graph));
205 Variable root = ProxyVariables.proxyVariableRoot(graph, context);
207 String sessionName = root.getParent(graph).getURI(graph);
208 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
209 SpreadsheetBook book = realm.getEngine();
210 SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
211 sc.setContent(value);
212 realm.asyncExec(new Runnable() {
217 SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
218 realm.getNodeManager().setValue(content, value, binding);
219 } catch (NodeManagerException e) {
220 Logger.defaultLogError(e);
227 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
228 if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
229 else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
230 else throw new DatabaseException("Unsupported value type " + value);
234 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
235 return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
236 //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
240 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
241 return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
242 // return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
246 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
247 return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
248 // return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
253 @SCLValue(type = "ValueAccessor")
254 public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
257 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
258 if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
259 if (!(value instanceof String)) throw new IllegalArgumentException();
261 if (((String)value).startsWith("=")) {
262 context.getParent(graph).setValue(graph, value, Bindings.STRING);
264 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
269 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
270 if (!(value instanceof String)) throw new IllegalArgumentException();
272 if (((String)value).startsWith("=")) {
273 context.getParent(graph).setValue(graph, value, Bindings.STRING);
275 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
280 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
281 return context.getParent(graph).getValue(graph, binding);
285 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
286 return context.getParent(graph).getValue(graph);
290 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
291 return context.getParent(graph).getDatatype(graph);
296 @SCLValue(type = "VariableMap")
297 public static VariableMap stringArrayChildren = new VariableMapImpl() {
300 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
302 TMap<String, Variable> map = new THashMap<String, Variable>();
303 getVariables(graph, context, map);
304 return map.get(name);
309 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
311 Resource resource = context.getRepresents(graph);
313 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
315 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
316 if(location == null) return map;
317 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
318 if(width == null) return map;
319 String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
320 if(array == null) return map;
322 int rows = array.length / width;
324 if(map == null) map = new HashMap<String,Variable>();
326 for(int offset=0,i=0;i<rows;i++) {
327 for(int j=0;j<width;j++) {
329 String value = array[offset++];
330 String valueLocation = Spreadsheets.offset(location, i, j);
332 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
333 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
335 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
346 @SCLValue(type = "VariableMap")
347 public static VariableMap queryRangeChildren = new VariableMapImpl() {
350 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
352 TMap<String, Variable> map = new THashMap<String, Variable>();
353 getVariables(graph, context, map);
354 return map.get(name);
359 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
361 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
363 String location = "A1";
367 Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
369 List<?> data = (List<?>)object;
371 if(map == null) map = new HashMap<String,Variable>();
373 for(Object o : data) {
374 if(o instanceof ITableCell) {
376 ITableCell cell = (ITableCell)o;
378 String valueLocation = Spreadsheets.offset(location, cell.getRow(), cell.getColumn());
380 ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
382 builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
383 builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
385 IFont font = cell.getFont();
387 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
390 int align = cell.getAlign();
391 builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
393 IColor foreground = cell.getFGColor();
394 if(foreground != null) {
395 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
398 IColor background = cell.getBGColor();
399 if(background != null) {
400 builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
403 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
408 } catch (DatabaseException e) {
409 throw (DatabaseException)e;
410 } catch (Throwable t) {
411 throw new DatabaseException(t);
421 @SCLValue(type = "VariableMap")
422 public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
425 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
427 if(ProxyVariables.isProxy(graph, context))
428 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
430 return super.getVariable(graph, context, name);
435 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
437 if(ProxyVariables.isProxy(graph, context))
438 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);
440 return super.getVariables(graph, context, map);
446 @SCLValue(type = "VariableMap")
447 public static VariableMap doubleArrayChildren = new VariableMapImpl() {
450 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
452 TMap<String, Variable> map = new THashMap<String, Variable>();
453 getVariables(graph, context, map);
454 return map.get(name);
459 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
461 Resource resource = context.getRepresents(graph);
463 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
465 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
466 if(location == null) return map;
467 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
468 if(width == null) return map;
469 double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
470 if(array == null) return map;
472 if(map == null) map = new HashMap<String,Variable>();
474 int rows = array.length / width;
476 for(int offset=0,i=0;i<rows;i++) {
477 for(int j=0;j<width;j++) {
479 double value = array[offset++];
480 String valueLocation = Spreadsheets.offset(location, i, j);
482 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
483 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
485 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
496 static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
498 public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
499 super(base, parent, other, name);
503 public Variable create(Variable base, Variable parent, Variable other, String name) {
504 return new SpreadsheetProxyChildVariable(base, parent, other, name);
507 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
509 if(CONTEXT_END.equals(name)) {
510 if(other instanceof ProxyChildVariable) {
511 // The context is also a proxy - let it do the job
512 return super.getPossibleChild(graph, name);
514 return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
518 return super.getPossibleChild(graph, name);
522 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
524 Collection<Variable> result = super.getChildren(graph);
525 if(!(base instanceof ProxyChildVariable)) {
526 Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
535 @SCLValue(type = "VariableMap")
536 public static VariableMap spreadsheetChildren = new VariableMapImpl() {
539 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
541 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
542 return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
546 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
547 Variable root = Variables.getRootVariable(graph);
548 return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
553 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
554 throws DatabaseException {
556 map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
558 if(map == null) map = new HashMap<String,Variable>();
559 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
565 public static class DefaultSheetCellEditor extends GraphCellEditorAdapter {
567 final public Variable sheet;
569 public DefaultSheetCellEditor(Variable sheet, Variable cell) {
575 public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
577 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
580 public void perform(WriteGraph graph) throws DatabaseException {
581 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
584 editor.edit(transaction, location, property, value, binding, callback);
591 public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
592 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
595 public void perform(WriteGraph graph) throws DatabaseException {
596 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
599 editor.edit(transaction, location, value, callback);
605 private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
606 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
607 Range range = Spreadsheets.decodePossibleCellAbsolute(location);
608 if(range == null) return null; //No editor found
610 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
611 if (cells.isEmpty()) {
615 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
618 if (cells.size() != 1)
619 throw new DatabaseException("Can edit only one cell at a time!");
621 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
625 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
627 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
630 public void perform(WriteGraph graph) throws DatabaseException {
632 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
633 Variable variable = sheet.getPossibleChild(graph, location);
634 if(variable != null) {
635 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
637 editor.copy(transaction, location, variant, null);
649 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
650 public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
652 final Variable sheet = context_.getParent(graph);
653 return new DefaultSheetCellEditor(sheet, null);
657 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
658 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
660 final Variable cell = context_.getParent(graph);
662 return new GraphCellEditorAdapter(cell) {
665 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
666 cell.setPropertyValue(graph, property, value, binding);
671 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
672 if(r == null) return 0;
673 Layer0 L0 = Layer0.getInstance(graph);
674 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
675 if(name.charAt(0) == 'R') {
676 return -Integer.parseInt(name.substring(3));
678 return Integer.parseInt(name);
682 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
683 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
685 Resource node = context_.getParent(graph).getRepresents(graph);
686 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
687 if(bean == null) return new int[0];
688 // There are n keys and n+1 resources
689 int[] result = new int[2*bean.n+1];
690 for(int i=0;i<bean.n;i++) {
691 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
692 result[2*i+1] = (int)bean.getKey(i).getValue();
694 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
699 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
700 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
702 String contextUri = context_.getURI(graph);
704 Variable line = context_.getParent(graph);
706 Collection<Variable> children = line.getChildren(graph);
707 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
708 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
709 for (Variable child : children) {
710 Resource repr = child.getRepresents(graph);
712 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
713 Integer styleId = null;
715 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
716 if (styleId == null) {
717 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
718 styleId = SpreadsheetStyle.empty().getStyleId();
721 LineContentBeanCell cell = new LineContentBeanCell(styleId);
723 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
725 if(variant != null) {
727 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
728 String expression = var.getPossiblePropertyValue(graph, "expression");
729 if (expression != null) {
730 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
732 cell.setContent(variant);
734 Range r = Spreadsheets.decodeCellAbsolute(child.getName(graph));
736 while(result.size() < r.startColumn + 1)
737 result.add(new LineContentBeanCell());
738 result.set(r.startColumn, cell);
743 LineContentBean bean = new LineContentBean();
744 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
749 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
750 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
752 Variable cells = context_.getParent(graph);
754 return new GraphCellEditorAdapter(cells) {
756 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
758 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
759 if(ClientModel.CONTENT.equals(property)) {
760 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
761 Variable runCell = null;
762 Object transactionContext = transaction.getContext();
763 if (transactionContext != null && transactionContext instanceof Variable) {
764 Variable varContext = (Variable) transactionContext;
765 Variable context = Variables.getContext(graph, varContext);
767 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
768 } catch (MissingVariableException e) {
769 // Creating new cell, need synchronizing
770 transaction.needSynchronization(cell.getParent(graph));
774 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
775 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
776 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
777 Variable runCell = null;
778 Object transactionContext = transaction.getContext();
779 if (transactionContext != null && transactionContext instanceof Variable) {
780 Variable varContext = (Variable) transactionContext;
781 Variable context = Variables.getContext(graph, varContext);
783 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
784 } catch (MissingVariableException e) {
785 //Creating new cell, need synchronizing
786 transaction.needSynchronization(cell.getParent(graph));
790 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
791 // SCL expressions always require synchronization
792 if(value.toString().startsWith("=="))
793 transaction.needSynchronization(cell.getParent(graph));
794 } else if(ClientModel.BORDER.equals(property)) {
795 Resource textCell = cell.getRepresents(graph);
796 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
797 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
798 builder.border((Integer)value);
799 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
800 } else if(ClientModel.ALIGN.equals(property)) {
801 Resource textCell = cell.getRepresents(graph);
802 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
803 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
804 builder.align((Integer)value);
805 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
806 } else if(ClientModel.LOCKED.equals(property)) {
807 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
808 } else if(ClientModel.ROW_SPAN.equals(property)) {
809 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
810 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
811 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
812 } else if(ClientModel.FONT.equals(property)) {
813 Resource textCell = cell.getRepresents(graph);
814 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
815 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
816 builder.font((Font)value);
817 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
818 } else if(ClientModel.FOREGROUND.equals(property)) {
819 Resource textCell = cell.getRepresents(graph);
820 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
821 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
822 builder.foreground((RGB.Integer)value);
823 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
824 } else if(ClientModel.BACKGROUND.equals(property)) {
825 Resource textCell = cell.getRepresents(graph);
826 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
827 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
828 builder.background((RGB.Integer)value);
829 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
833 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
835 Variable bookVariable = Variables.getContext(graph, cell);
836 Resource book = bookVariable.getRepresents(graph);
837 Resource createdStyle = null;
839 SpreadsheetStyle style = builder.build();
840 int styleId = style.getStyleId();
842 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
843 for (Resource eStyle : existingStyles) {
844 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
845 if (eStyleId == styleId) {
846 createdStyle = eStyle;
850 if (createdStyle == null) {
851 style = builder.name("Style_" + existingStyles.size()).build();
852 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
855 graph.deny(textCell, SHEET.Cell_HasStyle);
856 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
857 if (cellsOfStyle.isEmpty()) {
858 graph.deny(styleContainer);
860 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
864 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
865 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
866 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
867 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
868 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
869 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
871 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
875 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
876 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
878 // Handle possible deletes
880 value = Variant.ofInstance("");
882 if (!transaction.isOperationMode()) {
883 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
886 Variable runCell = null;
887 Object transactionContext = transaction.getContext();
888 if (transactionContext != null && transactionContext instanceof Variable) {
889 Variable varContext = (Variable) transactionContext;
890 Variable context = Variables.getContext(graph, varContext);
892 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
893 } catch (MissingVariableException e) {
894 // Creating cell for the first time so no runCell available at this time, needs synchronization
895 transaction.needSynchronization(cell.getParent(graph));
900 if (runCell != null) {
901 System.out.println("All.edit " + runCell.getURI(graph));
902 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
907 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
908 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
910 Variable runCell = null;
911 Object transactionContext = transaction.getContext();
912 if (transactionContext != null && transactionContext instanceof Variable) {
913 Variable varContext = (Variable) transactionContext;
914 Variable context = Variables.getContext(graph, varContext);
915 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
918 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
919 Variant content = null;
920 if (object instanceof Variant) {
921 content = (Variant)object;
922 } else if (object instanceof Double) {
923 content = Variant.ofInstance((Double)object);
924 } else if (object instanceof Float) {
925 content = Variant.ofInstance((Float)object);
926 } else if (object instanceof Integer) {
927 content = Variant.ofInstance((Integer)object);
928 } else if (object instanceof Long) {
929 content = Variant.ofInstance((Long)object);
930 } else if (object instanceof String) {
931 content = Variant.ofInstance((String)object);
932 } else if (object instanceof Variable) {
933 content = Variant.ofInstance((Variable)object);
935 throw new DatabaseException("");
937 variant.setValue(content);
944 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
945 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
946 return ProxyVariables.inputVariable(graph, sheet);
949 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
950 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
951 return ProxyVariables.proxySessionVariable(graph, sheet);
954 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
955 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
956 Resource model = Variables.getModel(graph, property);
957 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
958 if(activeRun != null) return activeRun;
959 return Variables.getConfigurationContext(graph, model);
962 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
963 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
964 return CompileSCLValueRequest.compileAndEvaluate(graph, context);