
/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.cli.cmd;

import java.io.PrintWriter;
import java.util.EnumSet;
import java.util.Map;

import org.jsimpledb.SessionMode;
import org.jsimpledb.cli.CliSession;
import org.jsimpledb.parse.expr.EvalException;
import org.jsimpledb.parse.expr.Node;
import org.jsimpledb.parse.expr.Value;
import org.jsimpledb.util.ParseContext;

public class EvalCommand extends AbstractCommand {

    public EvalCommand() {
        super("eval -f:force expr:expr");
    }

    @Override
    public String getHelpSummary() {
        return "Evaluates the specified Java expression";
    }

    @Override
    public String getHelpDetail() {
        return "The expression is evaluated within a transaction. If an exception occurs, the transaction is rolled back"
          + " unless the `-f' flag is given, in which case it will be committed anyway.";
    }

    @Override
    public EnumSet<SessionMode> getSessionModes() {
        return EnumSet.allOf(SessionMode.class);
    }

    @Override
    public CliSession.Action getAction(CliSession session, ParseContext ctx, boolean complete, Map<String, Object> params) {
        final Node expr = (Node)params.get("expr");
        final boolean force = params.containsKey("force");
        return new CliSession.TransactionalAction() {
            @Override
            public void run(CliSession session) throws Exception {
                final PrintWriter writer = session.getWriter();
                final Value value;
                final Object result;
                try {
                    result = (value = expr.evaluate(session)).get(session);
                } catch (EvalException e) {
                    if (!force && session.getMode().hasCoreAPI())
                        session.getTransaction().setRollbackOnly();
                    writer.println(session.getErrorMessagePrefix() + e.getMessage());
                    if (session.isVerbose())
                        e.printStackTrace(writer);
                    return;
                }
                if (value != Value.NO_VALUE)
                    writer.println(result);
            }
        };
    }
}


@@ -1067,27 +1067,20 @@
  public 
-CliSession.
+Eval
 Action g
@@ -1308,47 +1308,794 @@
 new 
-CliSession.TransactionalAction() %7B%0A    
+EvalAction(expr, force);%0A    %7D%0A%0A// EvalAction%0A%0A    /**%0A     * Special %7B@link CliSession.Action%7D used by the %7B@link EvalCommand%7D allowing access to the%0A     * %7B@link EvalException%7D that occurred, if any.%0A     *%0A     * %3Cp%3E%0A     * This class is needed because %7B@link EvalCommand%7D catches and handles %7B@link EvalException%7Ds%0A     * thrown during expression evaluation itself, swallowing them, making it appear as if the%0A     * command were always successful.%0A     */%0A    public static class EvalAction implements CliSession.TransactionalAction %7B%0A%0A        private final Node expr;%0A        private final boolean force;%0A        private EvalException evalException;%0A%0A        private EvalAction(Node expr, boolean force) %7B%0A            this.expr = expr;%0A            this.force = force;%0A        %7D%0A%0A
     
@@ -2108,20 +2108,16 @@
 verride%0A
-    
         
@@ -2179,28 +2179,24 @@
             
-  
-  
 final PrintW
@@ -2239,28 +2239,24 @@
             
-    
 final Value 
@@ -2270,28 +2270,24 @@
             
-   
- 
 final Object
@@ -2311,22 +2311,14 @@
     
-    
 try %7B%0A
-    
     
@@ -2397,20 +2397,16 @@
         
-    
 %7D catch 
@@ -2421,32 +2421,68 @@
 eption e) %7B%0A    
+            this.evalException = e;%0A
                 
@@ -2547,20 +2547,16 @@
         
-    
 session.
@@ -2599,36 +2599,32 @@
                 
- 
-   
 writer.println(s
@@ -2685,28 +2685,24 @@
             
-    
 if (session.
@@ -2734,20 +2734,16 @@
         
-  
-  
 e.printS
@@ -2773,28 +2773,24 @@
             
-    
 return;%0A    
@@ -2793,34 +2793,26 @@
             
-   
- 
 %7D%0A
-    
             
@@ -2840,20 +2840,16 @@
 _VALUE)%0A
-    
         
@@ -2892,24 +2892,331 @@
     
-    %7D%0A        %7D;
+%7D%0A%0A        /**%0A         * Get the %7B@link EvalException%7D that occurred when evaluating the expression, if any.%0A         *%0A         * @return exception thrown during evaluation, or null if evaluation was successful%0A         */%0A        public EvalException getEvalException() %7B%0A            return this.evalException;%0A        %7D
 %0A   
@@ -3220,9 +3220,8 @@
     %7D%0A%7D%0A
-%0A

Refactor EvalCommand to parse EvalAction's to allow error access.