]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java
032acfcfce722809848b8fceeeac10bb9bd19800
[simantics/platform.git] / bundles / org.simantics.spreadsheet.graph / src / org / simantics / spreadsheet / graph / SpreadsheetGraphUtils.java
1 package org.simantics.spreadsheet.graph;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.ObjectOutputStream;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.simantics.Simantics;
16 import org.simantics.databoard.Bindings;
17 import org.simantics.databoard.binding.mutable.Variant;
18 import org.simantics.databoard.util.binary.RandomAccessBinary;
19 import org.simantics.datatypes.DatatypeResource;
20 import org.simantics.datatypes.literal.Font;
21 import org.simantics.datatypes.literal.RGB;
22 import org.simantics.datatypes.utils.BTree;
23 import org.simantics.db.ReadGraph;
24 import org.simantics.db.Resource;
25 import org.simantics.db.WriteGraph;
26 import org.simantics.db.common.request.ObjectsWithType;
27 import org.simantics.db.common.utils.LiteralFileUtil;
28 import org.simantics.db.exception.DatabaseException;
29 import org.simantics.db.exception.ServiceException;
30 import org.simantics.db.layer0.util.Layer0Utils;
31 import org.simantics.db.layer0.variable.Variable;
32 import org.simantics.db.layer0.variable.Variables;
33 import org.simantics.db.service.ClusteringSupport;
34 import org.simantics.layer0.Layer0;
35 import org.simantics.scl.runtime.tuple.Tuple2;
36 import org.simantics.simulator.toolkit.StandardRealm;
37 import org.simantics.spreadsheet.Range;
38 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
39 import org.simantics.spreadsheet.resource.SpreadsheetResource;
40 import org.simantics.spreadsheet.util.SpreadsheetUtils;
41 import org.simantics.structural.synchronization.client.Synchronizer;
42
43 import gnu.trove.iterator.TObjectIntIterator;
44 import gnu.trove.map.hash.TObjectIntHashMap;
45
46 public class SpreadsheetGraphUtils {
47
48     public static File extractInitialCondition(ReadGraph graph, Resource ic) throws DatabaseException, IOException {
49
50         SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
51
52         File temp = Simantics.getTempfile("excel","ic");
53
54         LiteralFileUtil.copyRandomAccessBinaryToFile(graph, ic, SR.InitialCondition_bytes, temp);
55         if (temp.length() == 0)
56             throw new FileNotFoundException("Snapshot file does not exist.\nThis seems to be a database bug that manifests as total loss of state file data.\nThis error prevents the program from crashing.");
57
58         return temp;
59         
60     }
61         
62     public static RandomAccessBinary getOrCreateRandomAccessBinary(WriteGraph graph, Resource initialCondition) throws DatabaseException, IOException {
63
64         SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
65         
66         // We put snapshot literals in their own clusters for now just to be safe
67         Resource literal = graph.getPossibleObject(initialCondition, SR.InitialCondition_bytes);
68         if (literal != null) {
69             RandomAccessBinary rab = graph.getRandomAccessBinary(literal);
70             rab.position(0);
71             rab.removeBytes(rab.length(), RandomAccessBinary.ByteSide.Right);
72             return rab;
73         } else {
74             Layer0 L0 = Layer0.getInstance(graph);
75             ClusteringSupport cs = graph.getService(ClusteringSupport.class);
76             literal = graph.newResource(cs.createCluster());
77             graph.claim(literal, L0.InstanceOf, null, L0.ByteArray);
78             graph.claim(initialCondition, SR.InitialCondition_bytes, SR.InitialCondition_bytes_Inverse, literal);
79             return graph.createRandomAccessBinary(literal, Bindings.BYTE_ARRAY.type(), null);
80         }
81     }
82
83     public static Resource saveInitialCondition(WriteGraph graph, Variable run, Resource container, String name) throws DatabaseException {
84
85                 String sessionName = run.getParent(graph).getURI(graph);
86
87                 Resource bookResource = run.getRepresents(graph);
88                 
89         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
90         SpreadsheetBook book = realm.getEngine();
91
92         try {
93         
94                 File temp = Simantics.getTempfile("excel", "ic");
95                 System.err.println("Saving initial condition to " + temp.getAbsolutePath());
96                 
97                         FileOutputStream fileOut = new FileOutputStream(temp);
98                         ObjectOutputStream out = new ObjectOutputStream(fileOut);
99                         out.writeObject(book);
100                         out.close();
101                         fileOut.close();
102                         
103                         Layer0 L0 = Layer0.getInstance(graph);
104                 SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
105                         Resource ic = graph.newResource();
106                         graph.claim(ic, L0.InstanceOf, SR.InitialCondition);
107                         graph.addLiteral(ic, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING);
108                 
109                 RandomAccessBinary rab = getOrCreateRandomAccessBinary(graph, ic);
110                 LiteralFileUtil.copyRandomAccessBinaryFromFile(temp, rab);
111                 
112                         graph.claim(container, L0.ConsistsOf, L0.PartOf, ic);
113                         
114                         graph.deny(bookResource, SR.HasInitialCondition);
115                         graph.claim(bookResource, SR.HasInitialCondition, ic);
116                         graph.claim(ic, SR.InitialCondition_ConditionOf, bookResource);
117                         
118                         setDefaultInitialConditionForBook(graph, bookResource, ic);
119
120                 return ic;
121                 
122         } catch (IOException e) {
123                 
124                 throw new DatabaseException(e);
125                 
126         }
127     }
128     
129     public static void setDefaultInitialConditionForBook(WriteGraph graph, Resource book, Resource ic) throws ServiceException {
130         SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
131         graph.deny(book, SR.Book_HasDefaultInitialCondition);
132         graph.claim(ic, SR.InitialCondition_DefaultConditionOf, book);
133     }
134
135     public static void evaluateAll(ReadGraph graph, Variable run) throws DatabaseException {
136
137                 String sessionName = run.getParent(graph).getURI(graph);
138         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
139         SpreadsheetBook book = realm.getEngine();
140         book.accept(new EvaluateAll(book));
141         
142     }
143
144     public static void invalidateAll(ReadGraph graph, Variable run) throws DatabaseException {
145
146                 String sessionName = run.getParent(graph).getURI(graph);
147         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
148         SpreadsheetBook book = realm.getEngine();
149         book.accept(new InvalidateAll());
150         realm.getNodeManager().refreshVariables();
151         
152     }
153     
154     public static boolean fullSynchronization(ReadGraph graph, Variable run) throws DatabaseException {
155         return partialSynchronization(graph, run, null);
156     }
157
158     public static boolean partialSynchronization(ReadGraph graph, Variable run, TObjectIntHashMap<Variable> changeFlags) throws DatabaseException {
159
160         Synchronizer synchronizer = new Synchronizer(graph);
161                 String sessionName = run.getParent(graph).getURI(graph);
162                 
163         Resource bookResource = run.getRepresents(graph);
164         Variable configuration = Variables.getVariable(graph, bookResource);
165         
166         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
167         SpreadsheetBook book = realm.getEngine();
168                         
169         SpreadsheetSynchronizationEventHandler handler = new SpreadsheetSynchronizationEventHandler(graph, book);
170         
171 //        System.err.println("sessionName : " + sessionName);
172 //        System.err.println("bookResource : " + graph.getURI(bookResource));
173 //        System.err.println("configuration : " + configuration.getURI(graph));
174 //        System.err.println("realm : " + realm);
175 //        System.err.println("book : " + book);
176         
177         if (changeFlags == null) {
178             synchronizer.fullSynchronization(configuration, handler);
179         } else {
180             
181             TObjectIntIterator<Variable> iter = changeFlags.iterator();
182             iter.advance();
183             Variable row = iter.key();
184             
185             Variable rowParent = row.getParent(graph);
186             while (!rowParent.equals(configuration)) {
187                 changeFlags.put(rowParent, 1);
188                 rowParent = rowParent.getParent(graph);
189             }
190             
191             changeFlags.put(configuration, 1);
192             
193             synchronizer.partialSynchronization(configuration, handler, changeFlags);
194         }
195         
196 //        book.accept(new InvalidateAll());
197 //        realm.getNodeManager().refreshVariables();
198 //        mapping.currentRevision = synchronizer.getHeadRevisionId();
199 //        mapping.setTrustUids(true);
200         // Clean up queries
201 //        QueryControl qc = g.getService(QueryControl.class);
202 //        qc.flush(g);
203 //        TimeLogger.log("Finished full synchronization");
204         realm.getNodeManager().fireNodeListeners();
205         return handler.getDidChanges();
206         
207     }
208
209     public static Variable findCell(ReadGraph graph, Variable run, String reference) throws DatabaseException {
210
211         int pos = reference.indexOf("!");
212         String sheetName = reference.substring(0, pos);
213         String cellName = reference.substring(pos+1);
214
215                 String sessionName = run.getParent(graph).getURI(graph);
216         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
217         SpreadsheetBook book = realm.getEngine();
218         SpreadsheetEngine engine = book.getEngine(sheetName);
219         if(engine == null) return null;
220         
221         Range r = SpreadsheetUtils.decodeCellAbsolute(cellName);
222         SpreadsheetLine line = engine.getLine(r.startRow);
223         if(line == null) return null;
224         
225         String path = line.getPath();
226         if(path == null) return null;
227         
228         Variable lineVariable = run.browse(graph, path);
229         if(lineVariable==null) return null;
230         
231         return lineVariable.getChild(graph, cellName);
232         
233     }
234
235     
236     public static boolean asBoolean(Object object) {
237         if(object instanceof Boolean) return (Boolean)object;
238         else if(object instanceof Number) return ((Number)object).doubleValue() != 0;
239         else if(object instanceof Variant) return asBoolean(((Variant)object).getValue());
240         else if(object instanceof String) {
241                 Double d = asDoubleWhereEmptyStringIsZero((String)object);
242                 if(d==null) return false;
243                 else return d != 0;
244         }
245         return false;
246     }
247     
248     public static String asString(Object object) {
249         if(object == null) return "";
250         if(object instanceof String) return (String)object;
251         if(object instanceof Number) {
252                 double dVal = ((Number)object).doubleValue();
253                 if(dVal == Math.floor(dVal)){
254                         return ""+((Number)object).intValue();
255                 } else {
256                         return object.toString();
257                 }
258         }
259         else if(object instanceof Variant) {
260                 Object o = ((Variant) object).getValue();
261                 if(o instanceof String) return (String)o;
262                 else if(o instanceof Number) asString((Number)o);
263                 else return o.toString();
264         }
265         return object.toString();
266     }
267     
268     public static Double asDoubleWhereEmptyStringIsZero(Object object){
269         if(object instanceof Number)
270                 return ((Number)object).doubleValue();
271         else if(object instanceof String) {
272                 try {
273                         if(((String)object).isEmpty())
274                                 return 0.0;
275                         return Double.parseDouble((String)object);
276                         } catch (NumberFormatException e) {
277                                 return null;
278                         }
279         } else if(object instanceof Variant) {
280                 Object o = ((Variant) object).getValue();
281                 return asDoubleWhereEmptyStringIsZero(o);
282         } else if (SpreadsheetCell.EMPTY == object) {
283                 return null;
284         }
285         return null;
286     }
287     
288     public static double asNumber(Object object) {
289         if(object instanceof Number) {
290                 return ((Number)object).doubleValue();
291         } else if(object instanceof String) {
292                 try {
293                         String str = (String)object;
294                         if(str.isEmpty()) return 0;
295                         return Double.parseDouble((String)object);
296                         } catch (NumberFormatException e) {
297                         return 0;
298                         }
299         } else if(object instanceof Variant) {
300                 Object o = ((Variant) object).getValue();
301                 return asNumber(o);
302         } else if (SpreadsheetCell.EMPTY == object) {
303                 return 0.0;
304         }
305                 
306         return 0.0;
307         
308     }
309     
310     public static Number asValidNumber(Object object) {
311         if(object instanceof Number) {
312                 return (Number)object;
313         } else if(object instanceof String) {
314                 try {
315                         return Double.parseDouble((String)object);
316                         } catch (NumberFormatException e) {
317                         return null;
318                         }
319         } else if(object instanceof Variant) {
320                 Object o = ((Variant) object).getValue();
321                 return asNumber(o);
322         } else if (SpreadsheetCell.EMPTY == object) {
323                 return null;
324         }
325                 
326         return null;
327         
328     }
329     
330     public static boolean matchCriteria(Object value, Object criteria) {
331         if(value==null || criteria==null) return false;
332         
333         if(value instanceof Variant){
334                 Double dVal = asDoubleWhereEmptyStringIsZero(value);
335                 if(dVal==null) value = ((Variant)value).getValue();
336                 else value = dVal;
337         }
338         if(criteria instanceof Variant){
339                 Double dVal = asDoubleWhereEmptyStringIsZero(criteria);
340                 if(dVal==null) criteria = ((Variant)criteria).getValue();
341                 else criteria = dVal;
342         }
343         
344         if(criteria instanceof Number && value instanceof Number) {
345                 Number nc = (asNumber(criteria));
346                 Number nv = (asNumber(value));
347                 return nc.equals(nv);
348         }
349         if(criteria instanceof String){
350                 boolean nums = false;
351                 Object valueObj = null;
352                         if(value instanceof Number){
353                                 valueObj = ((Number)value).doubleValue();
354                                 nums = true;
355                         }
356                         else valueObj = value.toString();
357                         
358                 String sc = criteria.toString();
359                         if(sc.length() >= 3){
360                                 String oper = sc.substring(0, 2);
361                                 String criteriaStr = sc.substring(2);
362                                 Double criteriaNum = null;
363                                 try {
364                                         criteriaNum = Double.parseDouble(criteriaStr);
365                                         if(oper.equals("<>")){
366                                                 if(!nums) return true;
367                                         }
368                                         else if(!nums) return false;
369                                         nums = true;
370                                 } catch (NumberFormatException e){
371                                         if(oper.equals("<>")){
372                                                 if(nums) return true;
373                                         }
374                                         else if(nums) return false;
375                                         nums = false;
376                                 }
377                                 
378                                 if(oper.equals(">=")){
379                                         if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) >= 0 ;
380                                         else return ((Number)valueObj).doubleValue() >= criteriaNum;
381                                 } else if(oper.equals("<=")){
382                                         if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) <= 0 ;
383                                         else return ((Number)valueObj).doubleValue() <= criteriaNum;
384                                 } else if(oper.equals("<>")){
385                                         if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) != 0 ;
386                                         else return ((Number)valueObj).doubleValue() != criteriaNum;
387                                 }
388                         }
389                 if(sc.length() >= 2){
390                         String oper = sc.substring(0, 1);
391                         String criteriaStr = sc.substring(1);
392                         Double criteriaNum = null;
393                         
394                         try {
395                                         criteriaNum = Double.parseDouble(criteriaStr);
396                                         if(!nums) return false;
397                                         nums = true;
398                                 } catch (NumberFormatException e){
399                                         if(nums) return false;
400                                         nums = false;
401                                 }
402                         if(oper.equals("<")){
403                                 if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) < 0;
404                                 else return ((Number)valueObj).doubleValue() < criteriaNum;
405                         } else if(oper.equals(">")){
406                                 if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) > 0;
407                                 else return ((Number)valueObj).doubleValue() > criteriaNum;
408                         } else if(oper.equals("=")){
409                                 if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) == 0;
410                                 else return ((Number)valueObj).doubleValue() == criteriaNum;
411                         }
412                 }
413                 return sc.equals(valueObj);
414         }
415         else if (criteria instanceof Number){
416                 return false;
417         }
418         throw new IllegalStateException();
419     }
420
421     public static boolean excelEquals(Object left, Object right) {
422         if(left instanceof String) {
423                 if(right instanceof String) {
424                         return ((String) left).toLowerCase().equals(((String) right).toLowerCase());
425                 }
426         }
427         return left.equals(right);
428     }
429     
430
431     public static List<Variable> possibleConfigurationCellVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
432         List<Variable> rowVariables = possibleConfigurationLineVariables(graph, sheet, range);
433         List<Variable> result = new ArrayList<>();
434         for (Variable variable : rowVariables) {
435             Collection<Variable> children = variable.getChildren(graph);
436             for (Variable child : children) {
437                 if (variableInRange(graph, child, range)) {
438                     result.add(child);
439                 }
440             }
441         }
442         return result;
443     }
444     
445     public static Map<Integer, Resource> possibleConfigurationLineResources(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
446         Variable lines = sheet.getPossibleChild(graph, "Lines");
447         if (lines == null)
448             throw new DatabaseException("Invalid input variable " + sheet.getURI(graph));
449         Resource linesR = lines.getRepresents(graph);
450         BTree bt = new BTree(graph, linesR);
451         List<Tuple2> tuples = bt.searchRangeBTree(graph, Variant.ofInstance(range.startRow), Variant.ofInstance(range.endRow));
452         Map<Integer, Resource> result = new HashMap<>(tuples.size());
453         for (Tuple2 tuple : tuples) {
454             Integer lineNumber = (Integer)((Variant)tuple.c0).getValue();
455             Resource resource = (Resource)tuple.c1;
456             result.put(lineNumber, resource);
457         }
458         return result; 
459     }
460     
461     public static List<Variable> possibleConfigurationLineVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
462         Map<Integer, Resource> rows = possibleConfigurationLineResources(graph, sheet, range);
463         List<Variable> result = new ArrayList<>(rows.size());
464         for (Resource row: rows.values()) {
465             Variable lineVar = Variables.getPossibleVariable(graph, row);
466             if (lineVar != null)
467                 result.add(lineVar);
468         }
469         return result;
470     }
471     
472     public static List<Variable> possibleRunLineVariables(ReadGraph graph, Variable sheetRun, Range range) throws DatabaseException {
473         
474         Variable run = sheetRun.getParent(graph);
475         
476         String sheetName = sheetRun.getName(graph);
477         String sessionName = run.getParent(graph).getURI(graph);
478         
479         StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
480         SpreadsheetBook book = realm.getEngine();
481         
482         SpreadsheetEngine engine = book.getEngine(sheetName);
483         if(engine == null) return null;
484         
485         List<Variable> result = new ArrayList<>();
486         
487         int end = range.endRow < engine.lines.getMaxRow() ? range.endRow : engine.lines.getMaxRow();
488         for (int i = range.startRow; i <= end; i++) {
489                 SpreadsheetLine line = engine.getLine(i);
490                 if(line == null)
491                         continue;
492                 
493                 String path = line.getPath();
494                 path = line.getPath();
495                 if(path == null)
496                         continue;
497                 
498                 Variable lineVariable = run.browse(graph, path);
499                 if(lineVariable==null)
500                         continue;
501                 result.add(lineVariable);
502         }
503     
504         return result;
505     }
506     
507     public static List<Variable> possibleRunCellVariables(ReadGraph graph, Variable sheetRun, Range range) throws DatabaseException {
508         List<Variable> runLineVariable = possibleRunLineVariables(graph, sheetRun, range);
509         List<Variable> result = new ArrayList<>();
510         for (Variable variable : runLineVariable) {
511 //              System.out.println("line: " + variable.getURI(graph));
512             for (Variable child : variable.getChildren(graph)) {
513 //              System.out.print("cell : " + child.getURI(graph));
514                 if (variableInRange(graph, child, range)) {
515                     result.add(child);
516                 }
517             }
518         }
519         return result;
520     }
521     
522     private static boolean variableInRange(ReadGraph graph, Variable child, Range range) throws DatabaseException {
523         String name = child.getName(graph);
524         Range childRange = SpreadsheetUtils.decodeCellAbsolute(name);
525 //        System.out.print(" and range " + childRange);
526         if (childRange != null && range.contains(childRange)) {
527 //              System.out.println(" => range.contains(childRange) = true");
528             return true;
529         }
530 //        System.out.println();
531         return false;
532     }
533     
534     public static Map<Integer, Resource> createConfigurationLineResources(WriteGraph graph, Variable sheet, Range range) throws DatabaseException {
535         Layer0 L0 = Layer0.getInstance(graph);
536         SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
537         
538         Variable lines = sheet.getPossibleChild(graph, "Lines");
539         if (lines == null)
540             throw new DatabaseException("Invalid input variable " + sheet.getURI(graph));
541         Resource linesR = lines.getRepresents(graph);
542         BTree bt = new BTree(graph, linesR);
543         
544         Map<Integer, Resource> result = new HashMap<>();
545         for (int lineNumber = range.startRow; lineNumber <= range.endRow; lineNumber++) {
546             Resource line = graph.newResource();
547             graph.claim(line, L0.InstanceOf, null, SHEET.Line);
548             graph.claimLiteral(line, L0.HasName, L0.NameOf, L0.String, "Row" + lineNumber, Bindings.STRING);
549             bt.insertBTree(graph, Variant.ofInstance(lineNumber), line);
550             result.put(lineNumber, line);
551         }
552         return result;
553     }
554
555     public static List<Variable> getOrCreateConfigurationCellVariables(WriteGraph graph, Variable sheet, Range range) throws DatabaseException {
556         
557         List<Variable> rows = possibleConfigurationLineVariables(graph, sheet, range);
558         if (rows.isEmpty()) {
559             createConfigurationLineResources(graph, sheet, range);
560             rows = possibleConfigurationLineVariables(graph, sheet, range);
561         }
562         
563         List<Variable> cells = possibleConfigurationCellVariables(graph, sheet, range);
564         if (cells.isEmpty()) {
565             Iterator<Variable> rowIterator = rows.iterator();
566             for (int rowNumber = range.startRow; rowNumber <= range.endRow; rowNumber++) {
567                 Variable row = rowIterator.next();
568                 for (int colNumber = range.startColumn; colNumber <= range.endColumn; colNumber++) {
569                     String location = SpreadsheetUtils.cellName(rowNumber, colNumber);
570                     defaultCreateCell(graph, row, location, new Variant(Bindings.STRING, ""));
571                 }
572             }
573         }
574         
575         cells = possibleConfigurationCellVariables(graph, sheet, range);
576         if(cells.isEmpty())
577             throw new DatabaseException("Unexpected problem while creating spreadsheet cell at '" + range + "'");
578         
579         return cells;
580     }
581     
582     private static void defaultCreateCell(WriteGraph graph, Variable parent, String location, Variant value) throws DatabaseException {
583
584         Layer0 L0 = Layer0.getInstance(graph);
585         SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
586         Resource container = parent.getRepresents(graph);
587         
588         Resource cell = graph.newResource();
589         graph.claim(cell, L0.InstanceOf, null, SHEET.TextCell);
590         graph.addLiteral(cell, L0.HasName, L0.NameOf, L0.String, location, Bindings.STRING);
591         graph.addLiteral(cell, SHEET.Cell_content, SHEET.Cell_content_Inverse, L0.Variant, value, Bindings.VARIANT);
592         graph.claim(cell, L0.PartOf, container);
593         
594         Resource book = Variables.getContext(graph, parent).getRepresents(graph);
595         
596         
597         Collection<Resource> objects = graph.sync(new ObjectsWithType(book, L0.ConsistsOf, SHEET.Style));
598         
599         int styleId = SpreadsheetStyle.empty().getStyleId();
600         Resource style = null;
601         for (Resource possibleStyle : objects) {
602             int possibleStyleId = graph.getRelatedValue2(possibleStyle, SHEET.Style_id, Bindings.INTEGER);
603             if (possibleStyleId == styleId) {
604                 style = possibleStyle;
605                 break;
606             }
607         }
608         
609         if (style == null) {
610             style = graph.newResource();
611             graph.claim(style, L0.InstanceOf, null, SHEET.Style);
612             graph.claim(style, L0.PartOf, book);
613             
614             int id = objects.size();
615             graph.claimLiteral(style, L0.HasName, "Style_" + id);
616             graph.claimLiteral(style, SHEET.Style_id, styleId, Bindings.INTEGER);
617         }
618         graph.claim(cell, SHEET.Cell_HasStyle, style);
619         Layer0Utils.addCommentMetadata(graph, "Created cell on location " + location + " with value " + value.toString());
620     }
621
622     public static Resource createStyle(WriteGraph graph, Resource book, SpreadsheetStyle sstyle) throws DatabaseException {
623         Layer0 L0 = Layer0.getInstance(graph);
624         SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
625         Resource style = graph.newResource();
626         graph.claim(style, L0.InstanceOf, null, SR.Style);
627         graph.claim(style, L0.PartOf, book);
628         
629         int styleId = sstyle.getStyleId();
630         String styleName = sstyle.name;
631         
632         graph.claimLiteral(style, L0.HasName, styleName);
633         //System.err.println("CREATING STYLE " + styleName + " WITH ID: " + styleId);
634         graph.claimLiteral(style, SR.Style_id, styleId, Bindings.INTEGER);
635         
636         DatatypeResource DATATYPES = DatatypeResource.getInstance(graph);
637         if (sstyle.foreground != null)
638             graph.claimLiteral(style, SR.Cell_foreground, DATATYPES.RGB_Integer, sstyle.foreground, RGB.Integer.BINDING);
639         if (sstyle.background != null)
640             graph.claimLiteral(style, SR.Cell_background, DATATYPES.RGB_Integer, sstyle.background, RGB.Integer.BINDING);
641         if (sstyle.align != -1)
642             graph.claimLiteral(style, SR.Cell_align, sstyle.align, Bindings.INTEGER);
643         if (sstyle.font != null)
644             graph.claimLiteral(style, SR.Cell_font, DATATYPES.Font, sstyle.font, Font.BINDING);
645         if (sstyle.border != -1)
646             graph.claimLiteral(style, SR.Cell_border, sstyle.border);
647         if (sstyle.formatString != null && !sstyle.formatString.isEmpty())
648             graph.claimLiteral(style, SR.Cell_formatString, sstyle.formatString, Bindings.STRING);
649         if (sstyle.formatIndex != -1)
650             graph.claimLiteral(style, SR.Cell_formatIndex, sstyle.formatIndex, Bindings.INTEGER);
651         
652         return style;
653     }
654     
655     public static Resource createBook(WriteGraph graph, Resource parent, String name) throws DatabaseException {
656         Layer0 L0 = Layer0.getInstance(graph);
657         SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
658         Resource book = graph.newResource();
659         graph.claim(book, L0.InstanceOf, SR.Book);
660         graph.claimLiteral(book, L0.HasName, L0.NameOf, L0.String, name, Bindings.STRING);
661         graph.claim(parent, L0.ConsistsOf, book);
662         
663         return book;
664     }
665     
666     public static Variable constructAndInitializeRunVariable(WriteGraph graph, Resource root) throws DatabaseException {
667         Variable run = SpreadsheetUtils.getBookVariable(graph, root);
668         SpreadsheetGraphUtils.fullSynchronization(graph, run);
669         SpreadsheetGraphUtils.evaluateAll(graph, run);
670         SpreadsheetGraphUtils.saveInitialCondition(graph, run, root, "Initial");
671         return run;
672     }
673
674 }