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.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); //Invalidation handled by SpreadsheetNodeManager
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.decodePossibleCellAbsolute(location);
624 if(range == null) return null; //No editor found
626 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
627 if (cells.isEmpty()) {
631 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
634 if (cells.size() != 1)
635 throw new DatabaseException("Can edit only one cell at a time!");
637 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
641 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
643 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
646 public void perform(WriteGraph graph) throws DatabaseException {
648 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
649 Variable variable = sheet.getPossibleChild(graph, location);
650 if(variable != null) {
651 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
653 editor.copy(transaction, location, variant, null);
666 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
667 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
669 final Variable cell = context_.getParent(graph);
671 return new GraphCellEditorAdapter(cell) {
674 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
675 cell.setPropertyValue(graph, property, value, binding);
680 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
681 if(r == null) return 0;
682 Layer0 L0 = Layer0.getInstance(graph);
683 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
684 if(name.charAt(0) == 'R') {
685 return -Integer.parseInt(name.substring(3));
687 return Integer.parseInt(name);
691 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
692 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
694 Resource node = context_.getParent(graph).getRepresents(graph);
695 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
696 if(bean == null) return new int[0];
697 // There are n keys and n+1 resources
698 int[] result = new int[2*bean.n+1];
699 for(int i=0;i<bean.n;i++) {
700 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
701 result[2*i+1] = (int)bean.getKey(i).getValue();
703 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
708 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
709 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
711 String contextUri = context_.getURI(graph);
713 Variable line = context_.getParent(graph);
715 Collection<Variable> children = line.getChildren(graph);
716 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
717 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
718 for (Variable child : children) {
719 Resource repr = child.getRepresents(graph);
721 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
722 Integer styleId = null;
724 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
725 if (styleId == null) {
726 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
727 styleId = SpreadsheetStyle.empty().getStyleId();
730 LineContentBeanCell cell = new LineContentBeanCell(styleId);
732 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
734 if(variant != null) {
736 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
737 String expression = var.getPossiblePropertyValue(graph, "expression");
738 if (expression != null) {
739 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
741 cell.setContent(variant);
743 Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));
745 while(result.size() < r.startColumn + 1)
746 result.add(new LineContentBeanCell());
747 result.set(r.startColumn, cell);
752 LineContentBean bean = new LineContentBean();
753 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
758 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
759 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
761 System.out.println("Context URI : " + context_.getURI(graph));
762 Variable cells = context_.getParent(graph);
763 System.out.println("Cell URI : " + cells.getURI(graph));
765 return new GraphCellEditorAdapter(cells) {
767 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
769 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
770 if(ClientModel.CONTENT.equals(property)) {
771 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
772 Variable runCell = null;
773 Object transactionContext = transaction.getContext();
774 if (transactionContext != null && transactionContext instanceof Variable) {
775 Variable varContext = (Variable) transactionContext;
776 Variable context = Variables.getContext(graph, varContext);
778 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
779 } catch (MissingVariableException e) {
780 // Creating new cell, need synchronizing
781 transaction.needSynchronization(cell.getParent(graph));
785 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
786 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
787 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
788 Variable runCell = null;
789 Object transactionContext = transaction.getContext();
790 if (transactionContext != null && transactionContext instanceof Variable) {
791 Variable varContext = (Variable) transactionContext;
792 Variable context = Variables.getContext(graph, varContext);
794 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
795 } catch (MissingVariableException e) {
796 //Creating new cell, need synchronizing
797 transaction.needSynchronization(cell.getParent(graph));
801 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
802 } else if(ClientModel.BORDER.equals(property)) {
803 Resource textCell = cell.getRepresents(graph);
804 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
805 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
806 builder.border((Integer)value);
807 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
808 } else if(ClientModel.ALIGN.equals(property)) {
809 Resource textCell = cell.getRepresents(graph);
810 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
811 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
812 builder.align((Integer)value);
813 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
814 } else if(ClientModel.LOCKED.equals(property)) {
815 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
816 } else if(ClientModel.ROW_SPAN.equals(property)) {
817 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
818 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
819 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
820 } else if(ClientModel.FONT.equals(property)) {
821 Resource textCell = cell.getRepresents(graph);
822 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
823 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
824 builder.font((Font)value);
825 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
826 } else if(ClientModel.FOREGROUND.equals(property)) {
827 Resource textCell = cell.getRepresents(graph);
828 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
829 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
830 builder.foreground((RGB.Integer)value);
831 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
832 } else if(ClientModel.BACKGROUND.equals(property)) {
833 Resource textCell = cell.getRepresents(graph);
834 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
835 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
836 builder.background((RGB.Integer)value);
837 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
841 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
843 Variable bookVariable = Variables.getContext(graph, cell);
844 Resource book = bookVariable.getRepresents(graph);
845 Resource createdStyle = null;
847 SpreadsheetStyle style = builder.build();
848 int styleId = style.getStyleId();
850 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
851 for (Resource eStyle : existingStyles) {
852 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
853 if (eStyleId == styleId) {
854 createdStyle = eStyle;
858 if (createdStyle == null) {
859 style = builder.name("Style_" + existingStyles.size()).build();
860 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
863 graph.deny(textCell, SHEET.Cell_HasStyle);
864 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
865 if (cellsOfStyle.isEmpty()) {
866 graph.deny(styleContainer);
868 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
870 // Variable runCell = null;
871 // Object transactionContext = transaction.getContext();
872 // if (transactionContext != null && transactionContext instanceof Variable) {
873 // Variable varContext = (Variable) transactionContext;
874 // Variable context = Variables.getContext(graph, varContext);
876 // runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
877 // } catch (MissingVariableException e) {
878 // //Creating new cell, need synchronizing
879 // transaction.needSynchronization(cell.getParent(graph));
882 // if (runCell != null) {
883 // Datatype type = new RecordType();
884 // Binding b = Bindings.getBinding(type);
885 // runCell.setPropertyValue(graph, SHEET.Cell_style, style, b);
889 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
890 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
891 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
892 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
893 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
894 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
896 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
900 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
901 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
903 // Handle possible deletes
905 value = Variant.ofInstance("");
907 if (!transaction.isOperationMode()) {
908 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
911 Variable runCell = null;
912 Object transactionContext = transaction.getContext();
913 if (transactionContext != null && transactionContext instanceof Variable) {
914 Variable varContext = (Variable) transactionContext;
915 Variable context = Variables.getContext(graph, varContext);
917 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
918 } catch (MissingVariableException e) {
919 // Creating cell for the first time so no runCell available at this time, needs synchronization
920 transaction.needSynchronization(cell.getParent(graph));
925 if (runCell != null) {
926 System.out.println("All.edit " + runCell.getURI(graph));
927 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
932 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
933 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
935 Variable runCell = null;
936 Object transactionContext = transaction.getContext();
937 if (transactionContext != null && transactionContext instanceof Variable) {
938 Variable varContext = (Variable) transactionContext;
939 Variable context = Variables.getContext(graph, varContext);
940 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
943 //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);
944 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
945 Variant content = null;
946 if (object instanceof Variant) {
947 content = (Variant)object;
948 } else if (object instanceof Double) {
949 content = Variant.ofInstance((Double)object);
950 } else if (object instanceof Float) {
951 content = Variant.ofInstance((Float)object);
952 } else if (object instanceof Integer) {
953 content = Variant.ofInstance((Integer)object);
954 } else if (object instanceof Long) {
955 content = Variant.ofInstance((Long)object);
956 } else if (object instanceof String) {
957 content = Variant.ofInstance((String)object);
958 } else if (object instanceof Variable) {
959 content = Variant.ofInstance((Variable)object);
961 throw new DatabaseException("");
963 variant.setValue(content);
970 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
971 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
972 return ProxyVariables.inputVariable(graph, sheet);
975 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
976 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
977 return ProxyVariables.proxySessionVariable(graph, sheet);
980 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
981 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
982 Resource model = Variables.getModel(graph, property);
983 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
984 if(activeRun != null) return activeRun;
985 return Variables.getConfigurationContext(graph, model);
988 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
989 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
990 return CompileSCLValueRequest.compileAndEvaluate(graph, context);