1 package org.simantics.spreadsheet.graph.function;
3 import java.io.StringReader;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.HashSet;
12 import java.util.function.Consumer;
14 import org.simantics.databoard.Bindings;
15 import org.simantics.databoard.Databoard;
16 import org.simantics.databoard.adapter.AdaptException;
17 import org.simantics.databoard.binding.Binding;
18 import org.simantics.databoard.binding.mutable.MutableVariant;
19 import org.simantics.databoard.binding.mutable.Variant;
20 import org.simantics.databoard.type.Datatype;
21 import org.simantics.datatypes.literal.Font;
22 import org.simantics.datatypes.literal.RGB;
23 import org.simantics.datatypes.utils.BTreeContentBean;
24 import org.simantics.db.ReadGraph;
25 import org.simantics.db.Resource;
26 import org.simantics.db.WriteGraph;
27 import org.simantics.db.common.request.ObjectsWithType;
28 import org.simantics.db.common.request.WriteRequest;
29 import org.simantics.db.common.utils.Logger;
30 import org.simantics.db.common.utils.NameUtils;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.db.layer0.exception.MissingVariableException;
33 import org.simantics.db.layer0.function.StandardChildDomainChildren;
34 import org.simantics.db.layer0.request.PossibleActiveRun;
35 import org.simantics.db.layer0.util.Layer0Utils;
36 import org.simantics.db.layer0.variable.ConstantChildVariable;
37 import org.simantics.db.layer0.variable.ConstantPropertyVariableBuilder;
38 import org.simantics.db.layer0.variable.ProxyChildVariable;
39 import org.simantics.db.layer0.variable.ProxyVariables;
40 import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
41 import org.simantics.db.layer0.variable.ValueAccessor;
42 import org.simantics.db.layer0.variable.Variable;
43 import org.simantics.db.layer0.variable.VariableMap;
44 import org.simantics.db.layer0.variable.VariableMapImpl;
45 import org.simantics.db.layer0.variable.Variables;
46 import org.simantics.db.request.Write;
47 import org.simantics.document.server.io.IColor;
48 import org.simantics.document.server.io.IFont;
49 import org.simantics.document.server.io.ITableCell;
50 import org.simantics.layer0.Layer0;
51 import org.simantics.scl.reflection.annotations.SCLValue;
52 import org.simantics.simulator.toolkit.StandardRealm;
53 import org.simantics.simulator.variable.exceptions.NodeManagerException;
54 import org.simantics.spreadsheet.CellEditor;
55 import org.simantics.spreadsheet.ClientModel;
56 import org.simantics.spreadsheet.Range;
57 import org.simantics.spreadsheet.Spreadsheets;
58 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
59 import org.simantics.spreadsheet.graph.SpreadsheetNodeManager;
60 import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
61 import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
62 import org.simantics.spreadsheet.resource.SpreadsheetResource;
63 import org.simantics.spreadsheet.solver.SheetNode;
64 import org.simantics.spreadsheet.solver.SpreadsheetBook;
65 import org.simantics.spreadsheet.solver.SpreadsheetCell;
66 import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
67 import org.simantics.spreadsheet.solver.SpreadsheetFormula;
68 import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
69 import org.simantics.spreadsheet.solver.SpreadsheetStyle;
70 import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
71 import org.simantics.spreadsheet.solver.formula.parser.ParseException;
72 import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
73 import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
74 import org.simantics.spreadsheet.synchronization.ExcelFormula;
75 import org.simantics.spreadsheet.synchronization.LineContentBean;
76 import org.simantics.spreadsheet.synchronization.LineContentBeanCell;
77 import org.simantics.spreadsheet.util.SpreadsheetUtils;
79 import gnu.trove.map.TMap;
80 import gnu.trove.map.hash.THashMap;
81 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
85 @SCLValue(type = "ReadGraph -> Resource -> a -> String")
86 public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
87 if(context instanceof Resource) {
88 return NameUtils.getSafeLabel(graph, ((Resource)context));
89 } else if (context instanceof Variable) {
90 Variable parent = ((Variable)context).getParent(graph);
91 Variable content = parent.getPossibleProperty(graph, ClientModel.CONTENT);
93 Databoard db = graph.getService(Databoard.class);
94 Variant variant = content.getValue(graph, db.VARIANT);
95 return variant.getValue().toString();
97 return parent.getName(graph);
100 throw new DatabaseException("Unknown context " + context);
104 private static Set<String> CLASSIFICATIONS = new HashSet<String>();
105 private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN);
108 CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
111 @SCLValue(type = "ValueAccessor")
112 public static ValueAccessor contentValueAccessor = new ValueAccessor() {
115 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
116 System.out.println("contentValueAccessor.context=" + context.getURI(graph));
117 if(value instanceof String) {
119 // Expressions are given as string
120 String text = (String)value;
121 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
122 if (text.startsWith("==")) {
124 if(ProxyVariables.isProxy(graph, context))
125 // SCL expressions are not supported in solver
128 if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
129 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
130 //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
131 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
136 Variable cell = context.getParent(graph);
137 System.out.println("setValue : " + cell.getURI(graph));
139 String formula = text.substring(1);
141 if (ProxyVariables.isProxy(graph, context)) {
143 SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
144 AstValue v = p.relation();
145 SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
146 setValueToEngine(graph, cell, context, sformula, SpreadsheetFormula.BINDING);
147 } catch (ParseException e) {
154 Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
155 Layer0Utils.claimLiteral(graph, cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
160 if(ProxyVariables.isProxy(graph, context)) {
162 Variable cell = context.getParent(graph);
163 setValueToEngine(graph, cell, context, value, binding);
167 // Values are given as Variant
168 String expression = context.getPossiblePropertyValue(graph, "expression");
169 if(expression != null) {
170 Object current_ = context.getPossibleValue(graph);
171 if(current_ instanceof Variable) {
172 Variable current = (Variable)current_;
173 Variant variant = (Variant)value;
174 Datatype dt = current.getDatatype(graph);
176 throw new DatabaseException();
178 Binding variableBinding = Bindings.getBinding(dt);
180 Object adapted = variant.getValue(variableBinding);
181 current.setValue(graph, adapted, variableBinding);
182 } catch (AdaptException e) {
183 Logger.defaultLogError(e);
187 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
188 Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
190 org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
191 //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
195 private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
196 Variable sheet = cell.getParent(graph);
198 if(Bindings.STRING.equals(binding) && !(value instanceof String))
199 System.err.println("asd");
201 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
203 while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
204 sheet = sheet.getParent(graph);
207 Range r = Spreadsheets.decodeCellAbsolute(cell.getName(graph));
209 Variable root = ProxyVariables.proxyVariableRoot(graph, context);
211 String sessionName = root.getParent(graph).getURI(graph);
212 StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
213 SpreadsheetBook book = realm.getEngine();
214 SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
215 sc.setContent(value);
216 realm.asyncExec(new Runnable() {
221 SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
222 realm.getNodeManager().setValue(content, value, binding);
223 } catch (NodeManagerException e) {
224 Logger.defaultLogError(e);
231 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
232 if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
233 else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
234 else throw new DatabaseException("Unsupported value type " + value);
238 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
239 return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
240 //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
244 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
245 return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
246 // return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
250 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
251 return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
252 // return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
257 @SCLValue(type = "ValueAccessor")
258 public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
261 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
262 if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
263 if (!(value instanceof String)) throw new IllegalArgumentException();
265 if (((String)value).startsWith("=")) {
266 context.getParent(graph).setValue(graph, value, Bindings.STRING);
268 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
273 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
274 if (!(value instanceof String)) throw new IllegalArgumentException();
276 if (((String)value).startsWith("=")) {
277 context.getParent(graph).setValue(graph, value, Bindings.STRING);
279 context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
284 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
285 return context.getParent(graph).getValue(graph, binding);
289 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
290 return context.getParent(graph).getValue(graph);
294 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
295 return context.getParent(graph).getDatatype(graph);
300 @SCLValue(type = "VariableMap")
301 public static VariableMap stringArrayChildren = new VariableMapImpl() {
304 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
306 TMap<String, Variable> map = new THashMap<String, Variable>();
307 getVariables(graph, context, map);
308 return map.get(name);
313 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
315 Resource resource = context.getRepresents(graph);
317 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
319 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
320 if(location == null) return map;
321 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
322 if(width == null) return map;
323 String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
324 if(array == null) return map;
326 int rows = array.length / width;
328 if(map == null) map = new HashMap<String,Variable>();
330 for(int offset=0,i=0;i<rows;i++) {
331 for(int j=0;j<width;j++) {
333 String value = array[offset++];
334 String valueLocation = Spreadsheets.offset(location, i, j);
336 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
337 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
339 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
350 @SCLValue(type = "VariableMap")
351 public static VariableMap queryRangeChildren = new VariableMapImpl() {
354 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
356 TMap<String, Variable> map = new THashMap<String, Variable>();
357 getVariables(graph, context, map);
358 return map.get(name);
363 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
365 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
367 String location = "A1";
371 Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
373 List<?> data = (List<?>)object;
375 if(map == null) map = new HashMap<String,Variable>();
377 for(Object o : data) {
378 if(o instanceof ITableCell) {
380 ITableCell cell = (ITableCell)o;
382 String valueLocation = Spreadsheets.offset(location, cell.getRow(), cell.getColumn());
384 ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
386 builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
387 builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
389 IFont font = cell.getFont();
391 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
394 int align = cell.getAlign();
395 builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
397 IColor foreground = cell.getFGColor();
398 if(foreground != null) {
399 builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
402 IColor background = cell.getBGColor();
403 if(background != null) {
404 builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
407 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
412 } catch (DatabaseException e) {
413 throw (DatabaseException)e;
414 } catch (Throwable t) {
415 throw new DatabaseException(t);
425 @SCLValue(type = "VariableMap")
426 public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
429 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
431 if(ProxyVariables.isProxy(graph, context))
432 return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
434 return super.getVariable(graph, context, name);
436 // TMap<String, Variable> map = new THashMap<String, Variable>();
437 // getVariables(graph, context, map);
438 // return map.get(name);
443 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
445 System.err.println("getVariables " + context.getURI(graph));
447 if(ProxyVariables.isProxy(graph, context))
448 return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);
450 return super.getVariables(graph, context, map);
456 @SCLValue(type = "VariableMap")
457 public static VariableMap doubleArrayChildren = new VariableMapImpl() {
460 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
462 TMap<String, Variable> map = new THashMap<String, Variable>();
463 getVariables(graph, context, map);
464 return map.get(name);
469 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
471 Resource resource = context.getRepresents(graph);
473 SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
475 String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
476 if(location == null) return map;
477 Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
478 if(width == null) return map;
479 double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
480 if(array == null) return map;
482 if(map == null) map = new HashMap<String,Variable>();
484 int rows = array.length / width;
486 for(int offset=0,i=0;i<rows;i++) {
487 for(int j=0;j<width;j++) {
489 double value = array[offset++];
490 String valueLocation = Spreadsheets.offset(location, i, j);
492 ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
493 ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
495 map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
506 static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
508 public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
509 super(base, parent, other, name);
513 public Variable create(Variable base, Variable parent, Variable other, String name) {
514 return new SpreadsheetProxyChildVariable(base, parent, other, name);
517 public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
519 if(CONTEXT_END.equals(name)) {
520 if(other instanceof ProxyChildVariable) {
521 // The context is also a proxy - let it do the job
522 return super.getPossibleChild(graph, name);
524 return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
528 return super.getPossibleChild(graph, name);
532 public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
534 Collection<Variable> result = super.getChildren(graph);
535 if(!(base instanceof ProxyChildVariable)) {
536 Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
545 @SCLValue(type = "VariableMap")
546 public static VariableMap spreadsheetChildren = new VariableMapImpl() {
549 public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
551 if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
552 return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
556 private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
557 Variable root = Variables.getRootVariable(graph);
558 return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
563 public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
564 throws DatabaseException {
566 map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
568 if(map == null) map = new HashMap<String,Variable>();
569 map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
576 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
577 public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
579 final Variable sheet = context_.getParent(graph);
581 return new GraphCellEditorAdapter(null) {
584 public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
586 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
589 public void perform(WriteGraph graph) throws DatabaseException {
590 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
593 editor.edit(transaction, location, property, value, binding, callback);
600 public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
601 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
604 public void perform(WriteGraph graph) throws DatabaseException {
605 CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
608 editor.edit(transaction, location, value, callback);
614 private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
615 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
616 Range range = Spreadsheets.decodePossibleCellAbsolute(location);
617 if(range == null) return null; //No editor found
619 List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
620 if (cells.isEmpty()) {
624 cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
627 if (cells.size() != 1)
628 throw new DatabaseException("Can edit only one cell at a time!");
630 return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
634 public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
636 SpreadsheetUtils.schedule(transaction, new WriteRequest() {
639 public void perform(WriteGraph graph) throws DatabaseException {
641 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
642 Variable variable = sheet.getPossibleChild(graph, location);
643 if(variable != null) {
644 CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
646 editor.copy(transaction, location, variant, null);
659 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
660 public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
662 final Variable cell = context_.getParent(graph);
664 return new GraphCellEditorAdapter(cell) {
667 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
668 cell.setPropertyValue(graph, property, value, binding);
673 private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
674 if(r == null) return 0;
675 Layer0 L0 = Layer0.getInstance(graph);
676 String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
677 if(name.charAt(0) == 'R') {
678 return -Integer.parseInt(name.substring(3));
680 return Integer.parseInt(name);
684 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
685 public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
687 Resource node = context_.getParent(graph).getRepresents(graph);
688 BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
689 if(bean == null) return new int[0];
690 // There are n keys and n+1 resources
691 int[] result = new int[2*bean.n+1];
692 for(int i=0;i<bean.n;i++) {
693 result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
694 result[2*i+1] = (int)bean.getKey(i).getValue();
696 result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
701 @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
702 public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
704 String contextUri = context_.getURI(graph);
706 Variable line = context_.getParent(graph);
708 Collection<Variable> children = line.getChildren(graph);
709 ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
710 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
711 for (Variable child : children) {
712 Resource repr = child.getRepresents(graph);
714 Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
715 Integer styleId = null;
717 styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
718 if (styleId == null) {
719 System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
720 styleId = SpreadsheetStyle.empty().getStyleId();
723 LineContentBeanCell cell = new LineContentBeanCell(styleId);
725 Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
727 if(variant != null) {
729 Variable var = child.getPossibleProperty(graph, SR.Cell_content);
730 String expression = var.getPossiblePropertyValue(graph, "expression");
731 if (expression != null) {
732 cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
734 cell.setContent(variant);
736 Range r = Spreadsheets.decodeCellAbsolute(child.getName(graph));
738 while(result.size() < r.startColumn + 1)
739 result.add(new LineContentBeanCell());
740 result.set(r.startColumn, cell);
745 LineContentBean bean = new LineContentBean();
746 bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
751 @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
752 public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
754 System.out.println("Context URI : " + context_.getURI(graph));
755 Variable cells = context_.getParent(graph);
756 System.out.println("Cell URI : " + cells.getURI(graph));
758 return new GraphCellEditorAdapter(cells) {
760 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
762 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
763 if(ClientModel.CONTENT.equals(property)) {
764 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
765 Variable runCell = null;
766 Object transactionContext = transaction.getContext();
767 if (transactionContext != null && transactionContext instanceof Variable) {
768 Variable varContext = (Variable) transactionContext;
769 Variable context = Variables.getContext(graph, varContext);
771 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
772 } catch (MissingVariableException e) {
773 // Creating new cell, need synchronizing
774 transaction.needSynchronization(cell.getParent(graph));
778 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
779 } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
780 System.err.println("cell: " + cell.getURI(graph));
781 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
782 Variable runCell = null;
783 Object transactionContext = transaction.getContext();
784 if (transactionContext != null && transactionContext instanceof Variable) {
785 Variable varContext = (Variable) transactionContext;
786 Variable context = Variables.getContext(graph, varContext);
788 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
789 } catch (MissingVariableException e) {
790 //Creating new cell, need synchronizing
791 transaction.needSynchronization(cell.getParent(graph));
795 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
796 // SCL expressions always require synchronization
797 if(value.toString().startsWith("=="))
798 transaction.needSynchronization(cell.getParent(graph));
799 } else if(ClientModel.BORDER.equals(property)) {
800 Resource textCell = cell.getRepresents(graph);
801 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
802 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
803 builder.border((Integer)value);
804 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
805 } else if(ClientModel.ALIGN.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.align((Integer)value);
810 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
811 } else if(ClientModel.LOCKED.equals(property)) {
812 cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);
813 } else if(ClientModel.ROW_SPAN.equals(property)) {
814 cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
815 } else if(ClientModel.COLUMN_SPAN.equals(property)) {
816 cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
817 } else if(ClientModel.FONT.equals(property)) {
818 Resource textCell = cell.getRepresents(graph);
819 Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
820 SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
821 builder.font((Font)value);
822 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
823 } else if(ClientModel.FOREGROUND.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.foreground((RGB.Integer)value);
828 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
829 } else if(ClientModel.BACKGROUND.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.background((RGB.Integer)value);
834 finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
838 private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
840 Variable bookVariable = Variables.getContext(graph, cell);
841 Resource book = bookVariable.getRepresents(graph);
842 Resource createdStyle = null;
844 SpreadsheetStyle style = builder.build();
845 int styleId = style.getStyleId();
847 Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
848 for (Resource eStyle : existingStyles) {
849 int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
850 if (eStyleId == styleId) {
851 createdStyle = eStyle;
855 if (createdStyle == null) {
856 style = builder.name("Style_" + existingStyles.size()).build();
857 createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
860 graph.deny(textCell, SHEET.Cell_HasStyle);
861 Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
862 if (cellsOfStyle.isEmpty()) {
863 graph.deny(styleContainer);
865 graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
869 private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
870 RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
871 RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
872 Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
873 Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
874 Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
876 return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
880 public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
881 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
883 // Handle possible deletes
885 value = Variant.ofInstance("");
887 if (!transaction.isOperationMode()) {
888 cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
891 Variable runCell = null;
892 Object transactionContext = transaction.getContext();
893 if (transactionContext != null && transactionContext instanceof Variable) {
894 Variable varContext = (Variable) transactionContext;
895 Variable context = Variables.getContext(graph, varContext);
897 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
898 } catch (MissingVariableException e) {
899 // Creating cell for the first time so no runCell available at this time, needs synchronization
900 transaction.needSynchronization(cell.getParent(graph));
905 if (runCell != null) {
906 System.out.println("All.edit " + runCell.getURI(graph));
907 runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
912 public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
913 SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
915 Variable runCell = null;
916 Object transactionContext = transaction.getContext();
917 if (transactionContext != null && transactionContext instanceof Variable) {
918 Variable varContext = (Variable) transactionContext;
919 Variable context = Variables.getContext(graph, varContext);
920 runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
923 //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);
924 Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
925 Variant content = null;
926 if (object instanceof Variant) {
927 content = (Variant)object;
928 } else if (object instanceof Double) {
929 content = Variant.ofInstance((Double)object);
930 } else if (object instanceof Float) {
931 content = Variant.ofInstance((Float)object);
932 } else if (object instanceof Integer) {
933 content = Variant.ofInstance((Integer)object);
934 } else if (object instanceof Long) {
935 content = Variant.ofInstance((Long)object);
936 } else if (object instanceof String) {
937 content = Variant.ofInstance((String)object);
938 } else if (object instanceof Variable) {
939 content = Variant.ofInstance((Variable)object);
941 throw new DatabaseException("");
943 variant.setValue(content);
950 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
951 public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
952 return ProxyVariables.inputVariable(graph, sheet);
955 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
956 public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
957 return ProxyVariables.proxySessionVariable(graph, sheet);
960 @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
961 public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
962 Resource model = Variables.getModel(graph, property);
963 Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
964 if(activeRun != null) return activeRun;
965 return Variables.getConfigurationContext(graph, model);
968 @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
969 public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
970 return CompileSCLValueRequest.compileAndEvaluate(graph, context);