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.StandardRealm;
33 import org.simantics.db.layer0.exception.MissingVariableException;
34 import org.simantics.db.layer0.function.StandardChildDomainChildren;
35 import org.simantics.db.layer0.request.PossibleActiveRun;
36 import org.simantics.db.layer0.util.Layer0Utils;
37 import org.simantics.db.layer0.variable.ConstantChildVariable;
38 import org.simantics.db.layer0.variable.ConstantPropertyVariableBuilder;
39 import org.simantics.db.layer0.variable.ProxyChildVariable;
40 import org.simantics.db.layer0.variable.ProxyVariables;
41 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
42 import org.simantics.db.layer0.variable.ValueAccessor;
43 import org.simantics.db.layer0.variable.Variable;
44 import org.simantics.db.layer0.variable.VariableMap;
45 import org.simantics.db.layer0.variable.VariableMapImpl;
46 import org.simantics.db.layer0.variable.Variables;
47 import org.simantics.db.request.Write;
48 import org.simantics.document.server.io.IColor;
49 import org.simantics.document.server.io.IFont;
50 import org.simantics.document.server.io.ITableCell;
51 import org.simantics.layer0.Layer0;
52 import org.simantics.scl.reflection.annotations.SCLValue;
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.graph.ExcelFormula;
58 import org.simantics.spreadsheet.graph.SheetNode;
59 import org.simantics.spreadsheet.graph.SpreadsheetBook;
60 import org.simantics.spreadsheet.graph.SpreadsheetCell;
61 import org.simantics.spreadsheet.graph.SpreadsheetCellContent;
62 import org.simantics.spreadsheet.graph.SpreadsheetFormula;
63 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
64 import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant;
65 import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
66 import org.simantics.spreadsheet.graph.SpreadsheetStyle;
67 import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder;
68 import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
69 import org.simantics.spreadsheet.graph.parser.ParseException;
70 import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;
71 import org.simantics.spreadsheet.graph.parser.ast.AstValue;
72 import org.simantics.spreadsheet.resource.SpreadsheetResource;
73 import org.simantics.spreadsheet.util.SpreadsheetUtils;
75 import gnu.trove.map.TMap;
76 import gnu.trove.map.hash.THashMap;
77 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
81 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
82 public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
83 if(context instanceof Resource) {
84 return NameUtils.getSafeLabel(graph, ((Resource)context));
85 } else if (context instanceof Variable) {
86 Variable parent = ((Variable)context).getParent(graph);
87 Variable content = parent.getPossibleProperty(graph, ClientModel.CONTENT);
89 Databoard db = graph.getService(Databoard.class);
90 Variant variant = content.getValue(graph, db.VARIANT);
91 return variant.getValue().toString();
93 return parent.getName(graph);
96 throw new DatabaseException("Unknown context " + context);
100 private static Set<String> CLASSIFICATIONS = new HashSet<String>();
101 private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN);
104 CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
107 @SCLValue(type = "ValueAccessor")
108 public static ValueAccessor contentValueAccessor = new ValueAccessor() {
111 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
112 System.out.println("contentValueAccessor.context=" + context.getURI(graph));
113 if(value instanceof String) {
115 // Expressions are given as string
116 String text = (String)value;
117 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
118 if (text.startsWith("==")) {
119 if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
120 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
121 //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
122 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
127 Variable cell = context.getParent(graph);
128 System.out.println("setValue : " + cell.getURI(graph));
130 String formula = text.substring(1);
132 if (ProxyVariables.isProxy(graph, context)) {
134 SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
135 AstValue v = p.relation();
136 SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
137 setValueToEngine(graph, cell, context, sformula, binding);
138 } catch (ParseException e) {
144 Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
145 graph.claimLiteral(cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
149 if(ProxyVariables.isProxy(graph, context)) {
151 Variable cell = context.getParent(graph);
152 setValueToEngine(graph, cell, context, value, binding);
156 // Values are given as Variant
157 String expression = context.getPossiblePropertyValue(graph, "expression");
158 if(expression != null) {
159 Object current_ = context.getPossibleValue(graph);
160 if(current_ instanceof Variable) {
161 Variable current = (Variable)current_;
162 Variant variant = (Variant)value;
163 Datatype dt = current.getDatatype(graph);
165 throw new DatabaseException();
167 Binding variableBinding = Bindings.getBinding(dt);
169 Object adapted = variant.getValue(variableBinding);
170 current.setValue(graph, adapted, variableBinding);
171 } catch (AdaptException e) {
172 Logger.defaultLogError(e);
176 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
177 Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
179 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
180 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
184 private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
185 Variable sheet = cell.getParent(graph);
187 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
189 while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
190 sheet = sheet.getParent(graph);
193 Range r = SpreadsheetUtils.decodeCellAbsolute(cell.getName(graph));
195 Variable root = ProxyVariables.proxyVariableRoot(graph, context);
197 String sessionName = root.getParent(graph).getURI(graph);
198 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
199 SpreadsheetBook book = realm.getEngine();
200 SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
201 sc.setContent(value);
202 // book.accept(new InvalidateAll());
203 List<SpreadsheetCell> changed = book.invalidate(sc);
204 realm.asyncExec(new Runnable() {
209 SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
210 realm.getNodeManager().setValue(content, value, binding);
211 // for(SpreadsheetCell cell : changed) {
212 // content = (SpreadsheetCellContent)cell.getProperties().get("content");
213 // realm.getNodeManager().setValue(content, value, binding);
215 } catch (NodeManagerException e) {
216 Logger.defaultLogError(e);
223 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
224 if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
225 else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
226 else throw new DatabaseException("Unsupported value type " + value);
230 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
231 return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
232 //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
236 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
237 return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
238 // return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
242 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
243 return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
244 // return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
249 @SCLValue(type = "ValueAccessor")
250 public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
253 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
254 if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
255 if (!(value instanceof String)) throw new IllegalArgumentException();
257 if (((String)value).startsWith("=")) {
258 context.getParent(graph).setValue(graph, value, Bindings.STRING);
260 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
265 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
266 if (!(value instanceof String)) throw new IllegalArgumentException();
268 if (((String)value).startsWith("=")) {
269 context.getParent(graph).setValue(graph, value, Bindings.STRING);
271 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
276 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
277 return context.getParent(graph).getValue(graph, binding);
281 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
282 return context.getParent(graph).getValue(graph);
286 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
287 return context.getParent(graph).getDatatype(graph);
292 @SCLValue(type = "VariableMap")
293 public static VariableMap stringArrayChildren = new VariableMapImpl() {
296 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
298 TMap<String, Variable> map = new THashMap<String, Variable>();
299 getVariables(graph, context, map);
300 return map.get(name);
305 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
307 Resource resource = context.getRepresents(graph);
309 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
311 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
312 if(location == null) return map;
313 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
314 if(width == null) return map;
315 String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
316 if(array == null) return map;
318 int rows = array.length / width;
320 if(map == null) map = new HashMap<String,Variable>();
322 for(int offset=0,i=0;i<rows;i++) {
323 for(int j=0;j<width;j++) {
325 String value = array[offset++];
326 String valueLocation = SpreadsheetUtils.offset(location, i, j);
328 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
329 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
331 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
342 @SCLValue(type = "VariableMap")
343 public static VariableMap queryRangeChildren = new VariableMapImpl() {
346 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
348 TMap<String, Variable> map = new THashMap<String, Variable>();
349 getVariables(graph, context, map);
350 return map.get(name);
355 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
357 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
359 String location = "A1";
363 Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
365 List<?> data = (List<?>)object;
367 if(map == null) map = new HashMap<String,Variable>();
369 for(Object o : data) {
370 if(o instanceof ITableCell) {
372 ITableCell cell = (ITableCell)o;
374 String valueLocation = SpreadsheetUtils.offset(location, cell.getRow(), cell.getColumn());
376 ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
378 builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
379 builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
381 IFont font = cell.getFont();
383 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
386 int align = cell.getAlign();
387 builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
389 IColor foreground = cell.getFGColor();
390 if(foreground != null) {
391 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
394 IColor background = cell.getBGColor();
395 if(background != null) {
396 builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
399 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
404 } catch (DatabaseException e) {
405 throw (DatabaseException)e;
406 } catch (Throwable t) {
407 throw new DatabaseException(t);
417 @SCLValue(type = "VariableMap")
418 public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
421 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
423 if(ProxyVariables.isProxy(graph, context))
424 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
426 return super.getVariable(graph, context, name);
428 // TMap<String, Variable> map = new THashMap<String, Variable>();
429 // getVariables(graph, context, map);
430 // return map.get(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 // Resource lines = context.getRepresents(graph);
442 // BTree bt = new BTree(graph, lines, true);
443 // List<Tuple2> entries = bt.entriesOfBTree(graph);
444 // for(Tuple2 tuple : entries) {
445 // Variant v = (Variant)tuple.get(0);
446 // Resource line = (Resource)tuple.get(1);
447 // String name = v.getValue().toString();
448 // Variable child = org.simantics.db.layer0.function.All.getStandardChildDomainChildVariable(graph, context, line, name);
449 // if(map == null) map = new THashMap<String,Variable>();
450 // map.put(name, child);
455 // return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
457 return super.getVariables(graph, context, map);
463 @SCLValue(type = "VariableMap")
464 public static VariableMap doubleArrayChildren = new VariableMapImpl() {
467 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
469 TMap<String, Variable> map = new THashMap<String, Variable>();
470 getVariables(graph, context, map);
471 return map.get(name);
476 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
478 Resource resource = context.getRepresents(graph);
480 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
482 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
483 if(location == null) return map;
484 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
485 if(width == null) return map;
486 double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
487 if(array == null) return map;
489 if(map == null) map = new HashMap<String,Variable>();
491 int rows = array.length / width;
493 for(int offset=0,i=0;i<rows;i++) {
494 for(int j=0;j<width;j++) {
496 double value = array[offset++];
497 String valueLocation = SpreadsheetUtils.offset(location, i, j);
499 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
500 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
502 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
513 static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
515 public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
516 super(base, parent, other, name);
520 public Variable create(Variable base, Variable parent, Variable other, String name) {
521 return new SpreadsheetProxyChildVariable(base, parent, other, name);
524 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
526 if(CONTEXT_END.equals(name)) {
527 if(other instanceof ProxyChildVariable) {
528 // The context is also a proxy - let it do the job
529 return super.getPossibleChild(graph, name);
531 return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
535 return super.getPossibleChild(graph, name);
539 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
541 Collection<Variable> result = super.getChildren(graph);
542 if(!(base instanceof ProxyChildVariable)) {
543 Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
552 @SCLValue(type = "VariableMap")
553 public static VariableMap spreadsheetChildren = new VariableMapImpl() {
556 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
558 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
559 return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
563 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
564 Variable root = Variables.getRootVariable(graph);
565 return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
570 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
571 throws DatabaseException {
573 map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
575 if(map == null) map = new HashMap<String,Variable>();
576 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
583 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
584 public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
586 final Variable sheet = context_.getParent(graph);
588 return new GraphCellEditorAdapter(null) {
591 public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
593 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
596 public void perform(WriteGraph graph) throws DatabaseException {
597 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
600 editor.edit(transaction, location, property, value, binding, callback);
607 public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
608 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
611 public void perform(WriteGraph graph) throws DatabaseException {
612 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
615 editor.edit(transaction, location, value, callback);
621 private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
622 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
623 Range range = SpreadsheetUtils.decodeCellAbsolute(location);
625 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
626 if (cells.isEmpty()) {
630 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
633 if (cells.size() != 1)
634 throw new DatabaseException("Can edit only one cell at a time!");
636 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
640 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
642 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
645 public void perform(WriteGraph graph) throws DatabaseException {
647 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
648 Variable variable = sheet.getPossibleChild(graph, location);
649 if(variable != null) {
650 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
652 editor.copy(transaction, location, variant, null);
665 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
666 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
668 final Variable cell = context_.getParent(graph);
670 return new GraphCellEditorAdapter(cell) {
673 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
674 cell.setPropertyValue(graph, property, value, binding);
679 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
680 if(r == null) return 0;
681 Layer0 L0 = Layer0.getInstance(graph);
682 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
683 if(name.charAt(0) == 'R') {
684 return -Integer.parseInt(name.substring(3));
686 return Integer.parseInt(name);
690 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
691 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
693 Resource node = context_.getParent(graph).getRepresents(graph);
694 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
695 if(bean == null) return new int[0];
696 // There are n keys and n+1 resources
697 int[] result = new int[2*bean.n+1];
698 for(int i=0;i<bean.n;i++) {
699 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
700 result[2*i+1] = (int)bean.getKey(i).getValue();
702 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
707 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
708 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
710 String contextUri = context_.getURI(graph);
712 Variable line = context_.getParent(graph);
714 Collection<Variable> children = line.getChildren(graph);
715 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
716 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
717 for (Variable child : children) {
718 Resource repr = child.getRepresents(graph);
720 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
721 Integer styleId = null;
723 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
724 if (styleId == null) {
725 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
726 styleId = SpreadsheetStyle.empty().getStyleId();
729 LineContentBeanCell cell = new LineContentBeanCell(styleId);
731 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
733 if(variant != null) {
735 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
736 String expression = var.getPossiblePropertyValue(graph, "expression");
737 if (expression != null) {
738 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
740 cell.setContent(variant);
742 Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));
744 while(result.size() < r.startColumn + 1)
745 result.add(new LineContentBeanCell());
746 result.set(r.startColumn, cell);
751 LineContentBean bean = new LineContentBean();
752 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
757 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
758 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
760 System.out.println("Context URI : " + context_.getURI(graph));
761 Variable cells = context_.getParent(graph);
762 System.out.println("Cell URI : " + cells.getURI(graph));
764 return new GraphCellEditorAdapter(cells) {
766 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
768 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
769 if(ClientModel.CONTENT.equals(property)) {
770 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
771 Variable runCell = null;
772 Object transactionContext = transaction.getContext();
773 if (transactionContext != null && transactionContext instanceof Variable) {
774 Variable varContext = (Variable) transactionContext;
775 Variable context = Variables.getContext(graph, varContext);
777 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
778 } catch (MissingVariableException e) {
779 // Creating new cell, need synchronizing
780 transaction.needSynchronization(cell.getParent(graph));
784 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
785 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
786 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
787 Variable runCell = null;
788 Object transactionContext = transaction.getContext();
789 if (transactionContext != null && transactionContext instanceof Variable) {
790 Variable varContext = (Variable) transactionContext;
791 Variable context = Variables.getContext(graph, varContext);
793 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
794 } catch (MissingVariableException e) {
795 //Creating new cell, need synchronizing
796 transaction.needSynchronization(cell.getParent(graph));
800 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
801 } else if(ClientModel.BORDER.equals(property)) {
802 Resource textCell = cell.getRepresents(graph);
803 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
804 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
805 builder.border((Integer)value);
806 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
807 } else if(ClientModel.ALIGN.equals(property)) {
808 Resource textCell = cell.getRepresents(graph);
809 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
810 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
811 builder.align((Integer)value);
812 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
813 } else if(ClientModel.LOCKED.equals(property)) {
814 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
815 } else if(ClientModel.ROW_SPAN.equals(property)) {
816 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
817 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
818 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
819 } else if(ClientModel.FONT.equals(property)) {
820 Resource textCell = cell.getRepresents(graph);
821 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
822 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
823 builder.font((Font)value);
824 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
825 } else if(ClientModel.FOREGROUND.equals(property)) {
826 Resource textCell = cell.getRepresents(graph);
827 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
828 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
829 builder.foreground((RGB.Integer)value);
830 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
831 } else if(ClientModel.BACKGROUND.equals(property)) {
832 Resource textCell = cell.getRepresents(graph);
833 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
834 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
835 builder.background((RGB.Integer)value);
836 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
840 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
842 Variable bookVariable = Variables.getContext(graph, cell);
843 Resource book = bookVariable.getRepresents(graph);
844 Resource createdStyle = null;
846 SpreadsheetStyle style = builder.build();
847 int styleId = style.getStyleId();
849 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
850 for (Resource eStyle : existingStyles) {
851 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
852 if (eStyleId == styleId) {
853 createdStyle = eStyle;
857 if (createdStyle == null) {
858 style = builder.name("Style_" + existingStyles.size()).build();
859 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
862 graph.deny(textCell, SHEET.Cell_HasStyle);
863 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
864 if (cellsOfStyle.isEmpty()) {
865 graph.deny(styleContainer);
867 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
869 // Variable runCell = null;
870 // Object transactionContext = transaction.getContext();
871 // if (transactionContext != null && transactionContext instanceof Variable) {
872 // Variable varContext = (Variable) transactionContext;
873 // Variable context = Variables.getContext(graph, varContext);
875 // runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
876 // } catch (MissingVariableException e) {
877 // //Creating new cell, need synchronizing
878 // transaction.needSynchronization(cell.getParent(graph));
881 // if (runCell != null) {
882 // Datatype type = new RecordType();
883 // Binding b = Bindings.getBinding(type);
884 // runCell.setPropertyValue(graph, SHEET.Cell_style, style, b);
888 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
889 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
890 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
891 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
892 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
893 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
895 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
899 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
900 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
902 // Handle possible deletes
904 value = Variant.ofInstance("");
906 if (!transaction.isOperationMode()) {
907 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
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);
916 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
917 } catch (MissingVariableException e) {
918 // Creating cell for the first time so no runCell available at this time, needs synchronization
919 transaction.needSynchronization(cell.getParent(graph));
924 if (runCell != null) {
925 System.out.println("All.edit " + runCell.getURI(graph));
926 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
931 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
932 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
934 Variable runCell = null;
935 Object transactionContext = transaction.getContext();
936 if (transactionContext != null && transactionContext instanceof Variable) {
937 Variable varContext = (Variable) transactionContext;
938 Variable context = Variables.getContext(graph, varContext);
939 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
942 //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);
943 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
944 Variant content = null;
945 if (object instanceof Variant) {
946 content = (Variant)object;
947 } else if (object instanceof Double) {
948 content = Variant.ofInstance((Double)object);
949 } else if (object instanceof Float) {
950 content = Variant.ofInstance((Float)object);
951 } else if (object instanceof Integer) {
952 content = Variant.ofInstance((Integer)object);
953 } else if (object instanceof Long) {
954 content = Variant.ofInstance((Long)object);
955 } else if (object instanceof String) {
956 content = Variant.ofInstance((String)object);
957 } else if (object instanceof Variable) {
958 content = Variant.ofInstance((Variable)object);
960 throw new DatabaseException("");
962 variant.setValue(content);
969 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
970 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
971 return ProxyVariables.inputVariable(graph, sheet);
974 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
975 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
976 return ProxyVariables.proxySessionVariable(graph, sheet);
979 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
980 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
981 Resource model = Variables.getModel(graph, property);
982 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
983 if(activeRun != null) return activeRun;
984 return Variables.getConfigurationContext(graph, model);
987 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
988 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
989 return CompileSCLValueRequest.compileAndEvaluate(graph, context);