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.Transaction;
58 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
59 import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
60 import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
61 import org.simantics.spreadsheet.resource.SpreadsheetResource;
62 import org.simantics.spreadsheet.solver.SheetNode;
63 import org.simantics.spreadsheet.solver.SpreadsheetBook;
64 import org.simantics.spreadsheet.solver.SpreadsheetCell;
65 import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
66 import org.simantics.spreadsheet.solver.SpreadsheetFormula;
67 import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
68 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
69 import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
70 import org.simantics.spreadsheet.solver.formula.parser.ParseException;
71 import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
72 import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
73 import org.simantics.spreadsheet.synchronization.ExcelFormula;
74 import org.simantics.spreadsheet.synchronization.LineContentBean;
75 import org.simantics.spreadsheet.synchronization.LineContentBeanCell;
76 import org.simantics.spreadsheet.util.SpreadsheetUtils;
78 import gnu.trove.map.TMap;
79 import gnu.trove.map.hash.THashMap;
80 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
84 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
85 public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
86 if(context instanceof Resource) {
87 return NameUtils.getSafeLabel(graph, ((Resource)context));
88 } else if (context instanceof Variable) {
89 Variable parent = ((Variable)context).getParent(graph);
90 Variable content = parent.getPossibleProperty(graph, ClientModel.CONTENT);
92 Databoard db = graph.getService(Databoard.class);
93 Variant variant = content.getValue(graph, db.VARIANT);
94 return variant.getValue().toString();
96 return parent.getName(graph);
99 throw new DatabaseException("Unknown context " + context);
103 private static Set<String> CLASSIFICATIONS = new HashSet<String>();
104 private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN);
107 CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
110 @SCLValue(type = "ValueAccessor")
111 public static ValueAccessor contentValueAccessor = new ValueAccessor() {
114 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
115 System.out.println("contentValueAccessor.context=" + context.getURI(graph));
116 if(value instanceof String) {
118 // Expressions are given as string
119 String text = (String)value;
120 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
121 if (text.startsWith("==")) {
122 if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
123 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
124 //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
125 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
130 Variable cell = context.getParent(graph);
131 System.out.println("setValue : " + cell.getURI(graph));
133 String formula = text.substring(1);
135 if (ProxyVariables.isProxy(graph, context)) {
137 SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
138 AstValue v = p.relation();
139 SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
140 setValueToEngine(graph, cell, context, sformula, binding);
141 } catch (ParseException e) {
147 Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
148 graph.claimLiteral(cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
152 if(ProxyVariables.isProxy(graph, context)) {
154 Variable cell = context.getParent(graph);
155 setValueToEngine(graph, cell, context, value, binding);
159 // Values are given as Variant
160 String expression = context.getPossiblePropertyValue(graph, "expression");
161 if(expression != null) {
162 Object current_ = context.getPossibleValue(graph);
163 if(current_ instanceof Variable) {
164 Variable current = (Variable)current_;
165 Variant variant = (Variant)value;
166 Datatype dt = current.getDatatype(graph);
168 throw new DatabaseException();
170 Binding variableBinding = Bindings.getBinding(dt);
172 Object adapted = variant.getValue(variableBinding);
173 current.setValue(graph, adapted, variableBinding);
174 } catch (AdaptException e) {
175 Logger.defaultLogError(e);
179 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
180 Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
182 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
183 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
187 private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
188 Variable sheet = cell.getParent(graph);
190 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
192 while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
193 sheet = sheet.getParent(graph);
196 Range r = SpreadsheetUtils.decodeCellAbsolute(cell.getName(graph));
198 Variable root = ProxyVariables.proxyVariableRoot(graph, context);
200 String sessionName = root.getParent(graph).getURI(graph);
201 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
202 SpreadsheetBook book = realm.getEngine();
203 SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
204 sc.setContent(value);
205 // book.accept(new InvalidateAll());
206 // List<SpreadsheetCell> changed = book.invalidate(sc); //Invalidation handled by SpreadsheetNodeManager
207 realm.asyncExec(new Runnable() {
212 SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
213 realm.getNodeManager().setValue(content, value, binding);
214 // for(SpreadsheetCell cell : changed) {
215 // content = (SpreadsheetCellContent)cell.getProperties().get("content");
216 // realm.getNodeManager().setValue(content, value, binding);
218 } catch (NodeManagerException e) {
219 Logger.defaultLogError(e);
226 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
227 if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
228 else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
229 else throw new DatabaseException("Unsupported value type " + value);
233 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
234 return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
235 //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
239 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
240 return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
241 // return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
245 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
246 return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
247 // return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
252 @SCLValue(type = "ValueAccessor")
253 public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
256 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
257 if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
258 if (!(value instanceof String)) throw new IllegalArgumentException();
260 if (((String)value).startsWith("=")) {
261 context.getParent(graph).setValue(graph, value, Bindings.STRING);
263 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
268 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
269 if (!(value instanceof String)) throw new IllegalArgumentException();
271 if (((String)value).startsWith("=")) {
272 context.getParent(graph).setValue(graph, value, Bindings.STRING);
274 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
279 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
280 return context.getParent(graph).getValue(graph, binding);
284 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
285 return context.getParent(graph).getValue(graph);
289 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
290 return context.getParent(graph).getDatatype(graph);
295 @SCLValue(type = "VariableMap")
296 public static VariableMap stringArrayChildren = new VariableMapImpl() {
299 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
301 TMap<String, Variable> map = new THashMap<String, Variable>();
302 getVariables(graph, context, map);
303 return map.get(name);
308 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
310 Resource resource = context.getRepresents(graph);
312 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
314 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
315 if(location == null) return map;
316 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
317 if(width == null) return map;
318 String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
319 if(array == null) return map;
321 int rows = array.length / width;
323 if(map == null) map = new HashMap<String,Variable>();
325 for(int offset=0,i=0;i<rows;i++) {
326 for(int j=0;j<width;j++) {
328 String value = array[offset++];
329 String valueLocation = SpreadsheetUtils.offset(location, i, j);
331 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
332 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
334 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
345 @SCLValue(type = "VariableMap")
346 public static VariableMap queryRangeChildren = new VariableMapImpl() {
349 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
351 TMap<String, Variable> map = new THashMap<String, Variable>();
352 getVariables(graph, context, map);
353 return map.get(name);
358 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
360 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
362 String location = "A1";
366 Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
368 List<?> data = (List<?>)object;
370 if(map == null) map = new HashMap<String,Variable>();
372 for(Object o : data) {
373 if(o instanceof ITableCell) {
375 ITableCell cell = (ITableCell)o;
377 String valueLocation = SpreadsheetUtils.offset(location, cell.getRow(), cell.getColumn());
379 ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
381 builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
382 builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
384 IFont font = cell.getFont();
386 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
389 int align = cell.getAlign();
390 builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
392 IColor foreground = cell.getFGColor();
393 if(foreground != null) {
394 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
397 IColor background = cell.getBGColor();
398 if(background != null) {
399 builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
402 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
407 } catch (DatabaseException e) {
408 throw (DatabaseException)e;
409 } catch (Throwable t) {
410 throw new DatabaseException(t);
420 @SCLValue(type = "VariableMap")
421 public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
424 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
426 if(ProxyVariables.isProxy(graph, context))
427 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
429 return super.getVariable(graph, context, name);
431 // TMap<String, Variable> map = new THashMap<String, Variable>();
432 // getVariables(graph, context, map);
433 // return map.get(name);
438 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
440 if(ProxyVariables.isProxy(graph, context))
441 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);
443 // Resource lines = context.getRepresents(graph);
445 // BTree bt = new BTree(graph, lines, true);
446 // List<Tuple2> entries = bt.entriesOfBTree(graph);
447 // for(Tuple2 tuple : entries) {
448 // Variant v = (Variant)tuple.get(0);
449 // Resource line = (Resource)tuple.get(1);
450 // String name = v.getValue().toString();
451 // Variable child = org.simantics.db.layer0.function.All.getStandardChildDomainChildVariable(graph, context, line, name);
452 // if(map == null) map = new THashMap<String,Variable>();
453 // map.put(name, child);
458 // return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
460 return super.getVariables(graph, context, map);
466 @SCLValue(type = "VariableMap")
467 public static VariableMap doubleArrayChildren = new VariableMapImpl() {
470 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
472 TMap<String, Variable> map = new THashMap<String, Variable>();
473 getVariables(graph, context, map);
474 return map.get(name);
479 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
481 Resource resource = context.getRepresents(graph);
483 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
485 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
486 if(location == null) return map;
487 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
488 if(width == null) return map;
489 double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
490 if(array == null) return map;
492 if(map == null) map = new HashMap<String,Variable>();
494 int rows = array.length / width;
496 for(int offset=0,i=0;i<rows;i++) {
497 for(int j=0;j<width;j++) {
499 double value = array[offset++];
500 String valueLocation = SpreadsheetUtils.offset(location, i, j);
502 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
503 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
505 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
516 static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
518 public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
519 super(base, parent, other, name);
523 public Variable create(Variable base, Variable parent, Variable other, String name) {
524 return new SpreadsheetProxyChildVariable(base, parent, other, name);
527 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
529 if(CONTEXT_END.equals(name)) {
530 if(other instanceof ProxyChildVariable) {
531 // The context is also a proxy - let it do the job
532 return super.getPossibleChild(graph, name);
534 return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
538 return super.getPossibleChild(graph, name);
542 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
544 Collection<Variable> result = super.getChildren(graph);
545 if(!(base instanceof ProxyChildVariable)) {
546 Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
555 @SCLValue(type = "VariableMap")
556 public static VariableMap spreadsheetChildren = new VariableMapImpl() {
559 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
561 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
562 return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
566 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
567 Variable root = Variables.getRootVariable(graph);
568 return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
573 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
574 throws DatabaseException {
576 map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
578 if(map == null) map = new HashMap<String,Variable>();
579 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
586 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
587 public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
589 final Variable sheet = context_.getParent(graph);
591 return new GraphCellEditorAdapter(null) {
594 public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
596 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
599 public void perform(WriteGraph graph) throws DatabaseException {
600 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
603 editor.edit(transaction, location, property, value, binding, callback);
610 public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
611 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
614 public void perform(WriteGraph graph) throws DatabaseException {
615 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
618 editor.edit(transaction, location, value, callback);
624 private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
625 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
626 Range range = SpreadsheetUtils.decodePossibleCellAbsolute(location);
627 if(range == null) return null; //No editor found
629 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
630 if (cells.isEmpty()) {
634 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
637 if (cells.size() != 1)
638 throw new DatabaseException("Can edit only one cell at a time!");
640 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
644 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
646 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
649 public void perform(WriteGraph graph) throws DatabaseException {
651 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
652 Variable variable = sheet.getPossibleChild(graph, location);
653 if(variable != null) {
654 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
656 editor.copy(transaction, location, variant, null);
669 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
670 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
672 final Variable cell = context_.getParent(graph);
674 return new GraphCellEditorAdapter(cell) {
677 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
678 cell.setPropertyValue(graph, property, value, binding);
683 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
684 if(r == null) return 0;
685 Layer0 L0 = Layer0.getInstance(graph);
686 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
687 if(name.charAt(0) == 'R') {
688 return -Integer.parseInt(name.substring(3));
690 return Integer.parseInt(name);
694 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
695 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
697 Resource node = context_.getParent(graph).getRepresents(graph);
698 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
699 if(bean == null) return new int[0];
700 // There are n keys and n+1 resources
701 int[] result = new int[2*bean.n+1];
702 for(int i=0;i<bean.n;i++) {
703 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
704 result[2*i+1] = (int)bean.getKey(i).getValue();
706 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
711 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
712 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
714 String contextUri = context_.getURI(graph);
716 Variable line = context_.getParent(graph);
718 Collection<Variable> children = line.getChildren(graph);
719 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
720 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
721 for (Variable child : children) {
722 Resource repr = child.getRepresents(graph);
724 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
725 Integer styleId = null;
727 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
728 if (styleId == null) {
729 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
730 styleId = SpreadsheetStyle.empty().getStyleId();
733 LineContentBeanCell cell = new LineContentBeanCell(styleId);
735 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
737 if(variant != null) {
739 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
740 String expression = var.getPossiblePropertyValue(graph, "expression");
741 if (expression != null) {
742 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
744 cell.setContent(variant);
746 Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));
748 while(result.size() < r.startColumn + 1)
749 result.add(new LineContentBeanCell());
750 result.set(r.startColumn, cell);
755 LineContentBean bean = new LineContentBean();
756 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
761 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
762 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
764 System.out.println("Context URI : " + context_.getURI(graph));
765 Variable cells = context_.getParent(graph);
766 System.out.println("Cell URI : " + cells.getURI(graph));
768 return new GraphCellEditorAdapter(cells) {
770 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
772 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
773 if(ClientModel.CONTENT.equals(property)) {
774 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
775 Variable runCell = null;
776 Object transactionContext = transaction.getContext();
777 if (transactionContext != null && transactionContext instanceof Variable) {
778 Variable varContext = (Variable) transactionContext;
779 Variable context = Variables.getContext(graph, varContext);
781 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
782 } catch (MissingVariableException e) {
783 // Creating new cell, need synchronizing
784 transaction.needSynchronization(cell.getParent(graph));
788 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
789 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
790 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
791 Variable runCell = null;
792 Object transactionContext = transaction.getContext();
793 if (transactionContext != null && transactionContext instanceof Variable) {
794 Variable varContext = (Variable) transactionContext;
795 Variable context = Variables.getContext(graph, varContext);
797 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
798 } catch (MissingVariableException e) {
799 //Creating new cell, need synchronizing
800 transaction.needSynchronization(cell.getParent(graph));
804 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
805 } else if(ClientModel.BORDER.equals(property)) {
806 Resource textCell = cell.getRepresents(graph);
807 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
808 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
809 builder.border((Integer)value);
810 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
811 } else if(ClientModel.ALIGN.equals(property)) {
812 Resource textCell = cell.getRepresents(graph);
813 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
814 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
815 builder.align((Integer)value);
816 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
817 } else if(ClientModel.LOCKED.equals(property)) {
818 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
819 } else if(ClientModel.ROW_SPAN.equals(property)) {
820 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
821 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
822 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
823 } else if(ClientModel.FONT.equals(property)) {
824 Resource textCell = cell.getRepresents(graph);
825 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
826 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
827 builder.font((Font)value);
828 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
829 } else if(ClientModel.FOREGROUND.equals(property)) {
830 Resource textCell = cell.getRepresents(graph);
831 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
832 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
833 builder.foreground((RGB.Integer)value);
834 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
835 } else if(ClientModel.BACKGROUND.equals(property)) {
836 Resource textCell = cell.getRepresents(graph);
837 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
838 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
839 builder.background((RGB.Integer)value);
840 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
844 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
846 Variable bookVariable = Variables.getContext(graph, cell);
847 Resource book = bookVariable.getRepresents(graph);
848 Resource createdStyle = null;
850 SpreadsheetStyle style = builder.build();
851 int styleId = style.getStyleId();
853 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
854 for (Resource eStyle : existingStyles) {
855 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
856 if (eStyleId == styleId) {
857 createdStyle = eStyle;
861 if (createdStyle == null) {
862 style = builder.name("Style_" + existingStyles.size()).build();
863 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
866 graph.deny(textCell, SHEET.Cell_HasStyle);
867 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
868 if (cellsOfStyle.isEmpty()) {
869 graph.deny(styleContainer);
871 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
873 // Variable runCell = null;
874 // Object transactionContext = transaction.getContext();
875 // if (transactionContext != null && transactionContext instanceof Variable) {
876 // Variable varContext = (Variable) transactionContext;
877 // Variable context = Variables.getContext(graph, varContext);
879 // runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
880 // } catch (MissingVariableException e) {
881 // //Creating new cell, need synchronizing
882 // transaction.needSynchronization(cell.getParent(graph));
885 // if (runCell != null) {
886 // Datatype type = new RecordType();
887 // Binding b = Bindings.getBinding(type);
888 // runCell.setPropertyValue(graph, SHEET.Cell_style, style, b);
892 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
893 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
894 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
895 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
896 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
897 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
899 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
903 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
904 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
906 // Handle possible deletes
908 value = Variant.ofInstance("");
910 if (!transaction.isOperationMode()) {
911 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
914 Variable runCell = null;
915 Object transactionContext = transaction.getContext();
916 if (transactionContext != null && transactionContext instanceof Variable) {
917 Variable varContext = (Variable) transactionContext;
918 Variable context = Variables.getContext(graph, varContext);
920 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
921 } catch (MissingVariableException e) {
922 // Creating cell for the first time so no runCell available at this time, needs synchronization
923 transaction.needSynchronization(cell.getParent(graph));
928 if (runCell != null) {
929 System.out.println("All.edit " + runCell.getURI(graph));
930 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
935 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
936 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
938 Variable runCell = null;
939 Object transactionContext = transaction.getContext();
940 if (transactionContext != null && transactionContext instanceof Variable) {
941 Variable varContext = (Variable) transactionContext;
942 Variable context = Variables.getContext(graph, varContext);
943 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
946 //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);
947 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
948 Variant content = null;
949 if (object instanceof Variant) {
950 content = (Variant)object;
951 } else if (object instanceof Double) {
952 content = Variant.ofInstance((Double)object);
953 } else if (object instanceof Float) {
954 content = Variant.ofInstance((Float)object);
955 } else if (object instanceof Integer) {
956 content = Variant.ofInstance((Integer)object);
957 } else if (object instanceof Long) {
958 content = Variant.ofInstance((Long)object);
959 } else if (object instanceof String) {
960 content = Variant.ofInstance((String)object);
961 } else if (object instanceof Variable) {
962 content = Variant.ofInstance((Variable)object);
964 throw new DatabaseException("");
966 variant.setValue(content);
973 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
974 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
975 return ProxyVariables.inputVariable(graph, sheet);
978 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
979 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
980 return ProxyVariables.proxySessionVariable(graph, sheet);
983 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
984 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
985 Resource model = Variables.getModel(graph, property);
986 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
987 if(activeRun != null) return activeRun;
988 return Variables.getConfigurationContext(graph, model);
991 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
992 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
993 return CompileSCLValueRequest.compileAndEvaluate(graph, context);