-package org.simantics.spreadsheet.graph;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.binding.Binding;
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
-import org.simantics.simulator.variable.exceptions.NodeManagerException;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.synchronization.LineNodeUpdater;
-import org.simantics.spreadsheet.graph.synchronization.LineUpdater;
-import org.simantics.spreadsheet.graph.synchronization.NullUpdater;
-import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent;
-import org.simantics.spreadsheet.graph.synchronization.StyleUpdater;
-import org.simantics.structural.synchronization.base.ModuleUpdaterBase;
-import org.simantics.structural.synchronization.base.ModuleUpdaterFactoryBase;
-import org.simantics.structural.synchronization.base.SolverNameUtil;
-import org.simantics.structural.synchronization.utils.ComponentFactory;
-import org.simantics.structural.synchronization.utils.MappingBase;
-import org.simantics.structural.synchronization.utils.Solver;
-
-import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
-import it.unimi.dsi.fastutil.longs.AbstractLongList;
-import it.unimi.dsi.fastutil.longs.AbstractLongSet;
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.longs.LongArraySet;
-import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
-
-public class SpreadsheetBook implements StandardNodeManagerSupport<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
-
- private static final long serialVersionUID = 7417208688311691396L;
-
- public Serializable NotAvailableError = new Serializable() {
- private static final long serialVersionUID = 2535371785498129460L;
- };
-
- public Long2ObjectOpenHashMap<AbstractLongSet> referenceMap = new Long2ObjectOpenHashMap<>();
-
- private Int2ObjectArrayMap<SpreadsheetStyle> styles = new Int2ObjectArrayMap<>();
-// public ObjectArrayList<SpreadsheetStyle> styles = new ObjectArrayList<SpreadsheetStyle>();
- public ArrayList<SpreadsheetEngine> sheets = new ArrayList<SpreadsheetEngine>();
-
- private SpreadsheetMapping mapping;
-
-
- private int idCounter = 1;
-
- public SpreadsheetBook() {
- getNewId(this);
- mapping = new SpreadsheetMapping(new SheetLineComponent(""));
- }
-
- public Map<Integer, SpreadsheetElement> children = new HashMap<>();
-
- private boolean iterationEnabled;
-
- public int getNewId(SpreadsheetElement element) {
- int result = idCounter++;
- children.put(result, element);
- return result;
- }
-
- public long getEngineIndex(SpreadsheetEngine engine) {
- for(int i=0;i<sheets.size();i++)
- if(sheets.get(i) == engine) return i;
- throw new IllegalStateException("Did not find sheet " + engine.getName());
- }
-
- public void registerReferences(long cell, AbstractLongList refs) {
- for(int i=0;i<refs.size();i++) {
- long key = refs.getLong(i);
- AbstractLongSet set = referenceMap.get(key);
- if(set == null) {
- set = new LongArraySet();
- referenceMap.put(key, set);
- }
- if(set.size() == 5) {
- AbstractLongSet newSet = new LongLinkedOpenHashSet();
- newSet.addAll(set);
- set = newSet;
- referenceMap.put(key, set);
- }
- set.add(cell);
- }
- }
-
- @Override
- public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
- Object value = getEngineValue(node);
- if(value instanceof Variant) return Bindings.VARIANT;
- if(value instanceof String) return Bindings.STRING;
- if(value instanceof Boolean) return Bindings.BOOLEAN;
- else return Bindings.VOID;
-
- }
-
- @Override
- public Object getEngineValue(SheetNode node) {
- if(node instanceof SpreadsheetCellContent) {
- try {
- SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
- Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
- if(content == null) return Variant.ofInstance("");
- if(content instanceof Variant) return content;
- else return Variant.ofInstance(content);
- } catch (Throwable t) {
- t.printStackTrace();
- return Variant.ofInstance(t.toString());
- }
- } else if (node instanceof SpreadsheetCellContentExpression) {
- SpreadsheetCellContentExpression scce = (SpreadsheetCellContentExpression)node;
- if (scce.cell.content instanceof SpreadsheetFormula) {
- SpreadsheetFormula formula = (SpreadsheetFormula)scce.cell.content;
- return formula.expression;
- } else if (scce.cell.content instanceof SpreadsheetSCLConstant) {
- SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) scce.cell.content;
- return "=" + sclConstant.expression;
- } else {
- System.out.println("Broken SpreadsheetCellContentExpression possibly due to overwriting an existing expression with a constant or something else (current content is " + scce.cell.content + ")");
- if (scce.cell.content instanceof Variant) {
- return scce.cell.content;
- } else {
- return Variant.ofInstance(scce.cell.content);
- }
- }
- } else if (node instanceof SpreadsheetTypeNode) {
- SpreadsheetTypeNode stn = (SpreadsheetTypeNode)node;
- return stn.uri;
- } else if (node instanceof SpreadsheetCellStyle) {
- int styleId = ((SpreadsheetCellStyle) node).cell.style;
- SpreadsheetStyle style = getStyle(styleId);
- if (style == null) {
- style = SpreadsheetStyle.empty();
- if (styleId != style.getStyleId())
- new Exception("different style ids!" + styleId + " " + style.getStyleId()).printStackTrace();
- addStyle(style);
- }
- return style;
- } else if (node instanceof SpreadsheetCellEditable) {
- boolean editable = ((SpreadsheetCellEditable) node).editable();
- return editable;
- }
- return null;
- }
-
- @Override
- public void setEngineValue(SheetNode node, Object value) {
- }
-
- @Override
- public String getName(SheetNode node) {
- return node.getName();
- }
-
- @Override
- public Map<String, SheetNode> getChildren(SheetNode node) {
- return node.getChildren();
- }
-
- @Override
- public Map<String, SheetNode> getProperties(SheetNode node) {
- return node.getProperties();
- }
-
- @Override
- public String getName() {
- return "";
- }
-
- @Override
- public Map<String, SpreadsheetEngine> getChildren() {
- Map<String,SpreadsheetEngine> result = new HashMap<String,SpreadsheetEngine>();
- for(SpreadsheetEngine engine : sheets)
- result.put(engine.getName(), engine);
- return result;
- }
-
- @Override
- public Map<String, SheetNode> getProperties() {
- return Collections.emptyMap();
- }
-
- public SpreadsheetCell get(String sheet, int row, int column) {
- SpreadsheetEngine engine = getEngine(sheet);
- if(engine == null) return null;
- SpreadsheetLine line = engine.getLine(row);
- if(line == null) return null;
- if(line.cells.size() <= column) return null;
- return line.cells.get(column);
- }
-
- public SpreadsheetCell get(SpreadsheetEngine engine, int row, int column) {
- SpreadsheetLine line = engine.getLine(row);
- if(line == null) return null;
- if(line.cells.size() <= column) return null;
- return line.cells.get(column);
- }
-
- public SpreadsheetEngine getEngine(String sheet) {
- for(SpreadsheetEngine engine : sheets)
- if(sheet.equals(engine.getName())) return engine;
- return null;
- }
-
- @Override
- public ModuleUpdaterBase<SheetLineComponent> createUpdater(String id) throws DatabaseException {
- if("http://www.simantics.org/Spreadsheet-1.2/Line".equals(id))
- return new LineUpdater(id);
- else if("http://www.simantics.org/Spreadsheet-1.2/LineNode".equals(id))
- return new LineNodeUpdater(id);
- else if ("http://www.simantics.org/Spreadsheet-1.2/Style".equals(id))
- return new StyleUpdater(id);
- else if("http://www.simantics.org/Spreadsheet-1.2/Lines".equals(id))
- return new NullUpdater(id);
- else if("http://www.simantics.org/Spreadsheet-1.2/Spreadsheet".equals(id))
- return new NullUpdater(id);
- else if("http://www.simantics.org/Spreadsheet-1.2/Book".equals(id))
- return new NullUpdater(id);
- else
- throw new IllegalStateException("createUpdater " + id);
- }
-
- @Override
- public SheetLineComponent create(String uid) {
- return new SheetLineComponent(uid);
- }
-
- @Override
- public String getFreshName(String parentName, String name) {
- return parentName + "/" + name;
- }
-
- @Override
- public String ensureNameIsVariationOf(String parentName, int id, String name) {
- if (parentName.isEmpty())
- return name;
- return parentName + "/" + name;
- }
-
- final static int COMP_ROOT_POS = "COMP_ROOT/".length();
-
- @Override
- public int getId(String name) {
-
- if("COMP_ROOT".equals(name)) return 1;
-
- String path = name.substring(COMP_ROOT_POS);
- String[] parts = path.split("/");
- Object o = resolve(parts, 0);
- if(o instanceof SpreadsheetLines) {
- return ((SpreadsheetLines)o).getId();
- } else if(o instanceof SpreadsheetLine) {
- return ((SpreadsheetLine)o).getId();
- } else if(o instanceof SpreadsheetEngine) {
- return ((SpreadsheetEngine)o).getId();
- } else if (o instanceof SpreadsheetStyle) {
- return ((SpreadsheetStyle) o).getId();
- }
-
- throw new IllegalStateException("Resolved object for parts " + Arrays.toString(parts) + " is not the right type! It is " + o);
-
- }
-
- Object resolve(String[] parts, int index) {
- String part = parts[index];
- if (part.startsWith("Style")) {
- for (SpreadsheetStyle style : styles.values()) {
- if (style.name.equals(part)) {
- return style;
- }
- }
- }
- SpreadsheetEngine engine = getEngine(part);
- if(engine == null) return 0;
- if(index == parts.length-1) return engine;
- else return engine.resolve(parts, index+1);
- }
-
- @Override
- public String getName(int id) {
- if(id == -2) return "http://www.simantics.org/Spreadsheet-1.2/Book";
- else if(id == -3) return "http://www.simantics.org/Spreadsheet-1.2/Spreadsheet";
- else if(id == -4) return "http://www.simantics.org/Spreadsheet-1.2/Lines";
- else if(id == -5)
- return "http://www.simantics.org/Spreadsheet-1.2/LineNode";
- else if (id == -6)
- return "http://www.simantics.org/Spreadsheet-1.2/Line";
- else if(id == -7)
- return "http://www.simantics.org/Spreadsheet-1.2/Style";
- else return "" + id;
- }
-
- @Override
- public int getModuleType(int id) {
- Serializable s = children.get(id);
- if(s instanceof SpreadsheetBook) return -2;
- else if(s instanceof SpreadsheetEngine) return -3;
- else if(s instanceof SpreadsheetLines) {
- if("Lines".equals(((SpreadsheetLines) s).getName()))
- return -4;
- else
- return -5;
- }
- else if(s instanceof SpreadsheetLine)
- return -6;
- else if (s instanceof SpreadsheetStyle)
- return -7;
- else throw new IllegalStateException();
- }
-
- @Override
- public void remove(int id) {
-
- SpreadsheetElement child = children.get(id);
- Optional<SpreadsheetElement> parent = child.getParent();
-
- if (parent.isPresent()) {
- parent.get().remove(child);
- children.remove(id);
- }
- }
-
- @Override
- public void addSubprocess(String name, String subprocessType) {
- ensureSubprocess(name);
- }
-
- public <T> T ensureSubprocess(String name) {
- String[] parts = name.split("/");
- if(parts.length == 2) {
- SpreadsheetEngine engine = getEngine(parts[1]);
- if(engine == null) {
- engine = new SpreadsheetEngine(this, parts[1]);
- sheets.add(engine);
- }
- return (T)engine;
- } else if (parts.length > 2) {
- SpreadsheetEngine engine = getEngine(parts[1]);
- return (T)engine.ensureSubprocess(parts, 2);
- }
- throw new IllegalStateException();
- }
-
-
- @Override
- public void includeSubprocess(String parentName, String subprocessName) {
- // Nop
- }
-
- @Override
- public <T> T getConcreteSolver() {
- return (T)this;
- }
-
- @Override
- public void accept(SpreadsheetVisitor v) {
- v.visit(this);
- }
-
- //Recursively find all SpreadsheetCells, invalidate them and return them all as a set
- public Set<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
- Set<SpreadsheetCell> result = new HashSet<>();
- result.add(cell);
- cell.invalidate();
- long refKey = cell.makeReferenceKey();
- AbstractLongSet refs = referenceMap.remove(refKey);
- if(refs == null) return result;
- for(long ref : refs) {
- long sheet = ref >> 40;
- long row = (ref >> 20) & 0xFFFFF;
- long col = (ref) & 0xFFFFF;
- SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col);
- result.addAll(invalidate(referer));
- }
- return result;
- }
-
- @Deprecated
- public List<SpreadsheetCell> invalidateShallow(SpreadsheetCell cell) {
- ArrayList<SpreadsheetCell> result = new ArrayList<>();
- result.add(cell);
- cell.invalidate();
- long refKey = cell.makeReferenceKey();
- AbstractLongSet refs = referenceMap.remove(refKey);
- if(refs == null) return result;
- for(long ref : refs) {
- long sheet = ref >> 40;
- long row = (ref >> 20) & 0xFFFFF;
- long col = (ref) & 0xFFFFF;
- SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col);
- invalidate(referer);
- result.add(referer);
- }
- return result;
- }
-
- public void addStyle(SpreadsheetStyle style) {
- if (style.name == null) {
- new Exception("Trying to add style to book without name!!").printStackTrace();
- return;
- }
- style.setSynchronizationId(getNewId(style));
- styles.put(style.getStyleId(), style);
- }
-
- public SpreadsheetStyle getStyle(int styleId) {
- return styles.get(styleId);
- }
-
- public MappingBase<SheetLineComponent> getMapping() {
- return mapping;
- }
-
- @Override
- public Optional<SpreadsheetElement> getParent() {
- return Optional.empty();
- }
-
- @Override
- public Collection<SpreadsheetElement> getSpreadsheetChildren() {
- return children.values();
- }
-
- @Override
- public void remove(SpreadsheetElement child) {
- // TODO Auto-generated method stub
-
- }
-
- public void setIterationEnabled(boolean value) {
- this.iterationEnabled = value;
- }
-
- public boolean isIterationEnabled() {
- return iterationEnabled;
- }
-
-}