package org.simantics.spreadsheet.graph.request; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.Stack; import org.simantics.basicexpression.analysis.DepthFirstAdapter; import org.simantics.basicexpression.node.AAddressValue; import org.simantics.basicexpression.node.AConstantValue; import org.simantics.basicexpression.node.AFunctionPrimary; import org.simantics.basicexpression.node.AMultMultiplicative; import org.simantics.basicexpression.node.APlusExpression; import org.simantics.basicexpression.node.ARangeValue; import org.simantics.basicexpression.node.ARviValue; import org.simantics.basicexpression.node.ASequenceArgList; import org.simantics.basicexpression.node.ASingleArgList; import org.simantics.basicexpression.node.ASingleRange; import org.simantics.basicexpression.node.AStringValue; import org.simantics.basicexpression.node.AVariablePrimary; import org.simantics.basicexpression.node.PArgList; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.Function; import org.simantics.db.layer0.adapter.Instances; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.layer0.Layer0; import org.simantics.spreadsheet.Range; import org.simantics.spreadsheet.Spreadsheets; public class SpreadsheetExpressionVisitor extends DepthFirstAdapter { public static final boolean DEBUG_APPLICATION = false; public static final boolean DEBUG = false; public static class ApplicationException extends Exception { private static final long serialVersionUID = 1L; public ApplicationException(String message) { super(message); } } final ReadGraph graph; final Variable cellVariable; final Resource model; final Resource sheet; final int row; final int column; // final EvaluationEnvironmentImpl env; Stack stack = new Stack(); HashMap builtins = new HashMap(); // class EvaluationEnvironmentImpl implements EvaluationEnvironment { // // private boolean ready = false; // private boolean valid = true; // public HashSet deps = new HashSet(); // // // @Override // public int getColumn() { // return column; // } // // @Override // public Model getModel() { // return model; // } // // @Override // public int getRow() { // return row; // } // // public void depend(Range range) { // deps.add(range); // } // // public void listen() { // ready = true; // } // // @Override // public void invalidate() { // // DependencyHandler handler = model.getAdapter(DependencyHandler.class); // // handler.invalidate(row, column); // if(!ready) return; // valid = false; // ThreadUtils.getNonBlockingWorkExecutor().execute(new Runnable() { // // @Override // public void run() { // // Cell cell = model.get(row, column); // UpdateHandler handler = cell.getAdapter(UpdateHandler.class); // if(handler != null) handler.update(); // // } // // }); // // } // // @Override // public boolean isDisposed() { // return !valid; // } // // } public SpreadsheetExpressionVisitor(ReadGraph graph, Variable cellVariable, int row, int column) throws DatabaseException { // assert(model != null); // // assert(graph != null); // // assert(sheet != null); this.graph = graph; this.cellVariable = cellVariable; this.model = Variables.getModel(graph, cellVariable); Resource cell = cellVariable.getPossiblePropertyValue(graph, Variables.RESOURCE); this.sheet = graph.getPossibleObject(cell, Layer0.getInstance(graph).PartOf); // this.sheet = sheet; // this.model = model; this.row = row; this.column = column; // // builtins.put("Sequence", new Sequence()); // builtins.put("Set", new Set()); // builtins.put("SetBlock", new SetBlock()); // builtins.put("Sum", new Sum()); // builtins.put("Naturals", new Naturals()); // // env = new EvaluationEnvironmentImpl(); // // SpreadsheetResource sr = SpreadsheetResource.getInstance(graph); // // builtins.put("SUBSCRIPT", new Runnable() { // // @Override // public void run() { // // try { // // int column = ((Double)stack.pop()).intValue(); // int row = ((Double)stack.pop()).intValue(); // Object value = stack.pop(); // // //System.out.println("subscript(value=" + value + " row=" + row + // " column=" + column + ")"); // // if(value instanceof Collection) { // stack.push(((Collection)value).toArray()[row]); // } // // } catch (Throwable t) { // t.printStackTrace(); // } // // } // // }); } public Object getResult() { return stack.pop(); } public void outAConstantValue(AConstantValue node) { if(DEBUG) System.out.println("outAConstantValue " + node); stack.push(Double.valueOf(node.toString())); } public void outAStringValue(AStringValue node) { if(DEBUG) System.out.println("outAStringValue " + node); String value = node.toString(); stack.push(value.substring(1, value.length() - 2).trim()); } public void outAAddressValue(AAddressValue node) { if(DEBUG) System.out.println("outAAddressValue " + node); stack.push('&' + node.getRange().toString()); } @Override public void outASingleRange(ASingleRange node) { if(DEBUG) System.out.println("outASingleRange " + node); } @Override public void outARviValue(ARviValue node) { if(DEBUG) System.out.println("outARviValue " + node); String rvi = node.toString().trim(); try { System.out.println("browsing at " + cellVariable.getURI(graph)); Variable var = cellVariable.browse(graph, rvi); stack.push(var); } catch (DatabaseException e) { e.printStackTrace(); } } @Override public void outAVariablePrimary(AVariablePrimary node) { if(DEBUG) System.out.println("outAVariablePrimary " + node); String identifier = node.toString().trim(); Range range = Spreadsheets.decodeRange(identifier, row, column); if (range.size() != 1) { ArrayList value = new ArrayList(); for (int c = range.startColumn; c <= range.endColumn; c++) { for (int r = range.startRow; r <= range.endRow; r++) { try { String location = Spreadsheets.cellName(r, c); Variable cell = cellVariable.getChild(graph, location); System.out.println("cell=" + cell.getURI(graph)); String label = cell.getPossiblePropertyValue(graph, "Label"); System.out.println("lavel=" + label); value.add(label); } catch (DatabaseException e) { value.add(null); } } } stack.push(value); // System.out.println("pushing " + value); return; } // try { // String location = SpreadsheetUtils.cellName(range.startRow, // range.startColumn); // stack.push(graph.syncRequest(new CellResult(sheet, model, location))); // } catch (DatabaseException e) { // stack.push(null); // } } public void outARangeValue(ARangeValue node) { if(DEBUG) System.out.println("outARangeValue " + node); String identifier = node.getRange().toString().trim(); // try { // Range range = SpreadsheetUtils.decodeRange(identifier, row, column); // // env.depend(range); // if (range.size() != 1) { // ArrayList value = new ArrayList(); // for (int c = range.startColumn; c <= range.endColumn; c++) { // for (int r = range.startRow; r <= range.endRow; r++) { // try { // String location = SpreadsheetUtils.cellName(r, c); // // value.add(graph // .syncRequest(new CellResult(sheet, model, location))); // } catch (DatabaseException e) { // value.add(null); // } // } // } // stack.push(value); // // System.out.println("pushing " + value); // return; // } // // try { // String location = SpreadsheetUtils.cellName(range.startRow, // range.startColumn); // stack.push(graph.syncRequest(new CellResult(sheet, model, location))); // } catch (DatabaseException e) { // stack.push(null); // } } private double extractValue(Object o) { if (o instanceof Number) { return ((Number) o).doubleValue(); } else if (o instanceof String) { return Double.valueOf((String) o); } else { return Double.NaN; } } public void outAPlusExpression(APlusExpression node) { if(DEBUG) System.out.println("outAPlusExpression " + node); Object o1 = stack.pop(); Object o2 = stack.pop(); double d1 = extractValue(o1); double d2 = extractValue(o2); stack.push(d1 + d2); // System.out.println("plus " + d1 + " " + d2); } public void outAMultMultiplicative(AMultMultiplicative node) { if(DEBUG) System.out.println("outAMultiplicative " + node); Object o1 = stack.pop(); Object o2 = stack.pop(); double d1 = extractValue(o1); double d2 = extractValue(o2); stack.push(d1 * d2); // System.out.println("mult " + d1 + " " + d2); } int countArguments(PArgList args) { if (args == null) return 0; if (args instanceof ASingleArgList) return 1; ASequenceArgList seq = (ASequenceArgList) args; return 1 + countArguments(seq.getArgList()); } public void outAFunctionPrimary(AFunctionPrimary node) { if(DEBUG) System.out.println("outAFunctionPrimary " + node); try { String functionName = node.getFunc().getText().replace("(", ""); if (DEBUG_APPLICATION) System.out.println("function apply " + functionName); Function function = builtins.get(functionName); if (function != null) { LinkedList args = new LinkedList(); int argc = countArguments(node.getArgList()); for (int i = 0; i < argc; i++) { args.addFirst(stack.pop()); } args.addFirst(sheet); args.addFirst(model); Object result = function.apply(graph, args); stack.push(result); } else { Layer0 L0 = Layer0.getInstance(graph); Instances instances = graph.adapt(L0.Function, Instances.class); Collection functions = instances.find(graph, model, "Name:" + functionName); if (DEBUG_APPLICATION) System.out.println("Found " + functions.size() + " matches."); if (functions != null && functions.size() == 1) { Resource functionResource = functions.iterator().next(); function = graph.adapt(functionResource, Function.class); LinkedList args = new LinkedList(); int argc = countArguments(node.getArgList()); for (int i = 0; i < argc; i++) { args.addFirst(stack.pop()); } args.addFirst(cellVariable); //args.addFirst(model); // System.out.println("args=" + // Arrays.toString(args.toArray())); Object result = function.apply(graph, args.toArray()); stack.push(result); } else { stack.push(null); } } } catch (DatabaseException e) { stack.push(null); } } }