[email protected] has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/1885

Change subject: Allow logical plan to be viewed as JSON / formatted JSON
......................................................................

Allow logical plan to be viewed as JSON / formatted JSON

Change-Id: I4dd62e355048a5b8a02e074049fe41e73e74e357
---
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
M asterixdb/asterix-app/pom.xml
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
M asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
M asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
A 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
A 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
A 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
M 
hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
18 files changed, 1,362 insertions(+), 299 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/85/1885/1

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
index cfd4e87..3db772c 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
@@ -48,6 +48,11 @@
         CLEAN_JSON,
         LOSSLESS_JSON
     };
+    public enum PlanFormat {
+        JSON,
+        CLEAN_JSON,
+        STRING
+    };
 
     /**
      * Produce out-of-band output for Hyracks Job.
@@ -106,6 +111,8 @@
 
     // Output format.
     private final OutputFormat fmt;
+    private final PlanFormat lpfmt;
+    private final PlanFormat oplpfmt;
 
     // Standard execution flags.
     private final boolean executeQuery;
@@ -115,8 +122,8 @@
     // Flags.
     private final Map<String, Boolean> flags;
 
-    public SessionConfig(OutputFormat fmt) {
-        this(fmt, true, true, true);
+    public SessionConfig(OutputFormat fmt, PlanFormat lpfmt,PlanFormat 
oplpfmt) {
+        this(fmt, true, true, true,lpfmt,oplpfmt);
     }
 
     /**
@@ -131,13 +138,19 @@
      *            Whether to execute the query or not.
      * @param generateJobSpec
      *            Whether to generate the Hyracks job specification (if
+     * @param lpfmt
+     *            Plan format for logical plan.
+     * @param oplpfmt
+     *            Plan format for optimized logical plan.
      */
-    public SessionConfig(OutputFormat fmt, boolean optimize, boolean 
executeQuery, boolean generateJobSpec) {
+    public SessionConfig(OutputFormat fmt, boolean optimize, boolean 
executeQuery, boolean generateJobSpec,PlanFormat lpfmt,PlanFormat oplpfmt) {
         this.fmt = fmt;
         this.optimize = optimize;
         this.executeQuery = executeQuery;
         this.generateJobSpec = generateJobSpec;
         this.flags = new HashMap<>();
+        this.lpfmt = lpfmt;
+        this.oplpfmt = oplpfmt;
     }
 
     /**
@@ -146,7 +159,16 @@
     public OutputFormat fmt() {
         return this.fmt;
     }
-
+    /**
+     * Retrieve the PlanFormat for this execution.
+     */
+    public PlanFormat getLpfmt() {
+        return this.lpfmt;
+    }
+    /**
+     * Retrieve the OptimizedPlanFormat for this execution.
+     */
+    public PlanFormat getOplpfmt() {return this.oplpfmt;}
     /**
      * Retrieve the value of the "execute query" flag.
      */
diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index beac085..61af21f 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -279,6 +279,11 @@
   </profiles>
   <dependencies>
     <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>2.2.3</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.hyracks</groupId>
       <artifactId>hyracks-control-cc</artifactId>
     </dependency>
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index 583302b..a93e4ac 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -18,17 +18,8 @@
  */
 package org.apache.asterix.api.common;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
 import org.apache.asterix.api.http.server.ResultUtil;
@@ -42,20 +33,12 @@
 import org.apache.asterix.common.utils.Job.SubmissionMode;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.compiler.provider.IRuleSetFactory;
-import org.apache.asterix.dataflow.data.common.ConflictingTypeResolver;
-import org.apache.asterix.dataflow.data.common.ExpressionTypeComputer;
-import 
org.apache.asterix.dataflow.data.common.MergeAggregationExpressionFactory;
-import org.apache.asterix.dataflow.data.common.MissableTypeComputer;
-import org.apache.asterix.dataflow.data.common.PartialAggregationTypeComputer;
+import org.apache.asterix.dataflow.data.common.*;
 import org.apache.asterix.external.feed.watch.FeedActivityDetails;
 import org.apache.asterix.formats.base.IDataFormat;
 import org.apache.asterix.jobgen.QueryLogicalExpressionJobGen;
 import org.apache.asterix.lang.aql.statement.SubscribeFeedStatement;
-import org.apache.asterix.lang.common.base.IAstPrintVisitorFactory;
-import org.apache.asterix.lang.common.base.IQueryRewriter;
-import org.apache.asterix.lang.common.base.IReturningStatement;
-import org.apache.asterix.lang.common.base.IRewriterFactory;
-import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.base.*;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
@@ -78,14 +61,10 @@
 import org.apache.hyracks.algebricks.compiler.api.ICompilerFactory;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.ExpressionRuntimeProvider;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IMergeAggregationExpressionFactory;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IMissableTypeComputer;
+import org.apache.hyracks.algebricks.core.algebra.expressions.*;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
+import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitorJson;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import 
org.apache.hyracks.algebricks.core.rewriter.base.AlgebricksOptimizationContext;
 import 
org.apache.hyracks.algebricks.core.rewriter.base.IOptimizationContextFactory;
@@ -99,8 +78,10 @@
 import org.apache.hyracks.api.job.JobSpecification;
 import org.apache.hyracks.control.common.config.OptionTypes;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.rmi.RemoteException;
+import java.util.*;
 
 /**
  * Provides helper methods for compilation of a query into a JobSpec and 
submission
@@ -156,10 +137,15 @@
     private void printPlanPrefix(SessionOutput output, String planName) {
         if (output.config().is(SessionConfig.FORMAT_HTML)) {
             output.out().println("<h4>" + planName + ":</h4>");
-            output.out().println("<pre>");
+            if(planName.equalsIgnoreCase("Logical plan"))
+            output.out().println("<pre class = query-plan>");
+            else if(planName.equalsIgnoreCase("Optimized logical plan"))
+                output.out().println("<pre class = query-optimized-plan>");
+            else output.out().println("<pre>");
         } else {
             output.out().println("----------" + planName + ":");
         }
+
     }
 
     private void printPlanPostfix(SessionOutput output) {
@@ -219,8 +205,16 @@
 
             printPlanPrefix(output, "Logical plan");
             if (rwQ != null || (statement != null && statement.getKind() == 
Statement.Kind.LOAD)) {
-                LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor(output.out());
-                PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+
+                
if(output.config().getLpfmt().equals(SessionConfig.PlanFormat.CLEAN_JSON)||output.config().getLpfmt().equals(SessionConfig.PlanFormat.JSON))
 {
+                    LogicalOperatorPrettyPrintVisitorJson pvisitor = new 
LogicalOperatorPrettyPrintVisitorJson(output.out());
+                    PlanPrettyPrinter.operatorID = 0;
+                    PlanPrettyPrinter.resetOperatorID(plan);
+                    PlanPrettyPrinter.printPlanJson(plan, pvisitor, 0);
+                }else{
+                    LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor(output.out());
+                    PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
+                }
             }
             printPlanPostfix(output);
         }
@@ -273,10 +267,17 @@
                 } else {
                     printPlanPrefix(output, "Optimized logical plan");
                     if (rwQ != null || (statement != null && 
statement.getKind() == Statement.Kind.LOAD)) {
-                        LogicalOperatorPrettyPrintVisitor pvisitor =
-                                new 
LogicalOperatorPrettyPrintVisitor(output.out());
+                         
if(output.config().getOplpfmt().equals(SessionConfig.PlanFormat.CLEAN_JSON)||output.config().getOplpfmt().equals(SessionConfig.PlanFormat.JSON))
 {
+                        LogicalOperatorPrettyPrintVisitorJson pvisitor = new 
LogicalOperatorPrettyPrintVisitorJson(output.out());
+                        PlanPrettyPrinter.operatorID = 0;
+                             PlanPrettyPrinter.resetOperatorID(plan);
+                        PlanPrettyPrinter.printPlanJson(plan, pvisitor, 0);
+
+                    } else {
+                        LogicalOperatorPrettyPrintVisitor pvisitor = new 
LogicalOperatorPrettyPrintVisitor(output.out());
                         PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
                     }
+                }
                     printPlanPostfix(output);
                 }
             }
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index 7874aa3..5386e54 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
@@ -18,23 +18,7 @@
  */
 package org.apache.asterix.api.http.server;
 
-import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-
+import io.netty.handler.codec.http.HttpResponseStatus;
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.asterix.common.config.GlobalConfig;
 import org.apache.asterix.common.context.IStorageComponentProvider;
@@ -50,6 +34,7 @@
 import org.apache.asterix.translator.IStatementExecutorFactory;
 import org.apache.asterix.translator.SessionConfig;
 import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
 import org.apache.asterix.translator.SessionOutput;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
@@ -62,10 +47,20 @@
 import org.apache.hyracks.http.server.utils.HttpUtil.ContentType;
 import org.apache.hyracks.http.server.utils.HttpUtil.Encoding;
 
-import io.netty.handler.codec.http.HttpResponseStatus;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
 
 public class ApiServlet extends AbstractServlet {
-
+    public  static  PlanFormat planFormat;
+    public  static PlanFormat opPlanFormat;
     private static final Logger LOGGER = 
Logger.getLogger(ApiServlet.class.getName());
     public static final String HTML_STATEMENT_SEPARATOR = "<!-- BEGIN -->";
 
@@ -96,8 +91,11 @@
         // Output format.
         PrintWriter out = response.writer();
         OutputFormat format;
+
         boolean csvAndHeader = false;
         String output = request.getParameter("output-format");
+        String plan = request.getParameter("plan-format");
+        String opPlan = request.getParameter("optimizedPlanFormat");
         try {
             format = OutputFormat.valueOf(output);
         } catch (IllegalArgumentException e) {
@@ -106,7 +104,22 @@
             // Default output format
             format = OutputFormat.CLEAN_JSON;
         }
-
+        try {
+            planFormat = PlanFormat.valueOf(plan);
+        } catch (IllegalArgumentException e) {
+            LOGGER.log(Level.INFO,
+                    plan + ": unsupported plan-format, using " + 
PlanFormat.CLEAN_JSON + " instead", e);
+            // Default output format
+            planFormat = PlanFormat.CLEAN_JSON;
+        }
+        try {
+            opPlanFormat = PlanFormat.valueOf(opPlan);
+        } catch (IllegalArgumentException e) {
+            LOGGER.log(Level.INFO,
+                    opPlan + ": unsupported optimized-plan-format, using " + 
PlanFormat.CLEAN_JSON + " instead", e);
+            // Default output format
+            opPlanFormat = PlanFormat.CLEAN_JSON;
+        }
         String query = request.getParameter("query");
         String wrapperArray = request.getParameter("wrapper-array");
         String printExprParam = request.getParameter("print-expr-tree");
@@ -138,7 +151,7 @@
             }
             IParser parser = parserFactory.createParser(query);
             List<Statement> aqlStatements = parser.parse();
-            SessionConfig sessionConfig = new SessionConfig(format, true, 
isSet(executeQuery), true);
+            SessionConfig sessionConfig = new SessionConfig(format, true, 
isSet(executeQuery), true,planFormat,opPlanFormat);
             sessionConfig.set(SessionConfig.FORMAT_HTML, true);
             sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, csvAndHeader);
             sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, 
isSet(wrapperArray));
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 9ee064e..3193621 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -18,14 +18,15 @@
  */
 package org.apache.asterix.api.http.server;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpResponseStatus;
 import org.apache.asterix.algebra.base.ILangExtension;
 import org.apache.asterix.api.http.servlet.ServletConstants;
 import org.apache.asterix.common.api.IApplicationContext;
@@ -40,13 +41,9 @@
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.metadata.MetadataManager;
 import org.apache.asterix.runtime.utils.ClusterStateManager;
-import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.*;
 import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
 import org.apache.asterix.translator.IStatementExecutor.Stats;
-import org.apache.asterix.translator.IStatementExecutorContext;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.asterix.translator.SessionConfig;
-import org.apache.asterix.translator.SessionOutput;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.application.IServiceContext;
 import org.apache.hyracks.api.exceptions.HyracksException;
@@ -55,16 +52,13 @@
 import org.apache.hyracks.http.server.utils.HttpUtil;
 import org.apache.hyracks.util.JSONUtil;
 
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import io.netty.handler.codec.http.HttpHeaderNames;
-import io.netty.handler.codec.http.HttpResponseStatus;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class QueryServiceServlet extends AbstractQueryApiServlet {
     private static final Logger LOGGER = 
Logger.getLogger(QueryServiceServlet.class.getName());
@@ -103,7 +97,9 @@
         FORMAT("format"),
         CLIENT_ID("client_context_id"),
         PRETTY("pretty"),
-        MODE("mode");
+        MODE("mode"),
+        PLAN_FORMAT("plan-format"),
+        OPTIMIZED_PLAN_FORMAT("optimized-plan-format");
 
         private final String str;
 
@@ -182,6 +178,8 @@
         String path;
         String statement;
         String format;
+        String lpfmt;
+        String oplpfmt;
         boolean pretty;
         String clientContextID;
         String mode;
@@ -250,7 +248,8 @@
         SessionOutput.ResultAppender appendStatus = 
ResultUtil.createResultStatusAppender();
 
         SessionConfig.OutputFormat format = getFormat(param.format);
-        SessionConfig sessionConfig = new SessionConfig(format);
+        //TODO:Shiva
+        SessionConfig sessionConfig = new SessionConfig(format, 
SessionConfig.PlanFormat.CLEAN_JSON, SessionConfig.PlanFormat.CLEAN_JSON);
         sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.pretty);
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
index 18aae8e..3dfa150 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
@@ -18,15 +18,11 @@
  */
 package org.apache.asterix.api.http.server;
 
-import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.asterix.app.translator.QueryTranslator;
 import org.apache.asterix.common.config.GlobalConfig;
@@ -53,12 +49,14 @@
 import org.apache.hyracks.http.server.AbstractServlet;
 import org.apache.hyracks.http.server.utils.HttpUtil;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
-import io.netty.handler.codec.http.HttpMethod;
-import io.netty.handler.codec.http.HttpResponseStatus;
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static 
org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
 
 public abstract class RestApiServlet extends AbstractServlet {
     private static final Logger LOGGER = 
Logger.getLogger(RestApiServlet.class.getName());
@@ -116,7 +114,7 @@
 
         SessionOutput.ResultAppender appendHandle = (app, handle) -> 
app.append("{ \"").append("handle")
                 .append("\":" + " \"").append(handle).append("\" }");
-        SessionConfig sessionConfig = new SessionConfig(format);
+        SessionConfig sessionConfig = new 
SessionConfig(format,ApiServlet.planFormat,ApiServlet.opPlanFormat);
 
         // If it's JSON or ADM, check for the "wrapper-array" flag. Default is
         // "true" for JSON and "false" for ADM. (Not applicable for CSV.)
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
index a9d24b9..0e1f275 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/java/AsterixJavaClient.java
@@ -18,10 +18,6 @@
  */
 package org.apache.asterix.api.java;
 
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.util.List;
-
 import org.apache.asterix.api.common.APIFramework;
 import org.apache.asterix.app.translator.QueryTranslator;
 import org.apache.asterix.common.context.IStorageComponentProvider;
@@ -36,9 +32,14 @@
 import org.apache.asterix.translator.IStatementExecutorFactory;
 import org.apache.asterix.translator.SessionConfig;
 import org.apache.asterix.translator.SessionConfig.OutputFormat;
+import org.apache.asterix.translator.SessionConfig.PlanFormat;
 import org.apache.asterix.translator.SessionOutput;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.job.JobSpecification;
+
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.List;
 
 public class AsterixJavaClient {
     private IHyracksClientConnection hcc;
@@ -79,7 +80,7 @@
     }
 
     public void compile() throws Exception {
-        compile(true, false, false, false, false, false, false);
+        compile(true, false, true, false, false, false, false);
     }
 
     public void compile(boolean optimize, boolean printRewrittenExpressions, 
boolean printLogicalPlan,
@@ -100,7 +101,7 @@
         List<Statement> statements = parser.parse();
         MetadataManager.INSTANCE.init();
 
-        SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize, 
true, generateBinaryRuntime);
+        SessionConfig conf = new SessionConfig(OutputFormat.ADM, optimize, 
true, generateBinaryRuntime,PlanFormat.CLEAN_JSON,PlanFormat.CLEAN_JSON);
         conf.setOOBData(false, printRewrittenExpressions, printLogicalPlan, 
printOptimizedPlan, printJob);
         if (printPhysicalOpsOnly) {
             conf.set(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS, true);
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
index ba44833..0169e8f 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/drivers/AsterixClientDriver.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.drivers;
 
-import java.io.FileReader;
-
 import org.apache.asterix.api.common.AsterixClientConfig;
 import org.apache.asterix.api.java.AsterixJavaClient;
 import org.apache.asterix.app.translator.DefaultStatementExecutorFactory;
@@ -29,6 +27,8 @@
 import org.apache.hyracks.api.client.HyracksConnection;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.kohsuke.args4j.CmdLineParser;
+
+import java.io.FileReader;
 
 public class AsterixClientDriver {
 
@@ -53,8 +53,10 @@
         }
         boolean exec = new Boolean(acc.execute);
         IHyracksClientConnection hcc = exec ? new 
HyracksConnection("localhost", acc.hyracksPort) : null;
+//        AsterixJavaClient q = compileQuery(hcc, acc.getArguments().get(0), 
new Boolean(acc.optimize),
+//                new Boolean(acc.onlyPhysical), exec || new 
Boolean(acc.hyracksJob));
         AsterixJavaClient q = compileQuery(hcc, acc.getArguments().get(0), new 
Boolean(acc.optimize),
-                new Boolean(acc.onlyPhysical), exec || new 
Boolean(acc.hyracksJob));
+                false, exec || new Boolean(acc.hyracksJob));
         if (exec) {
             q.execute();
         }
diff --git a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html 
b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
index cffec6f..a07ab8b 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
@@ -19,24 +19,24 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-<meta name="description" content="ASTERIX WEB PAGE" />
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link
-       
href='http://fonts.googleapis.com/css?family=Bitter|PT+Sans+Caption|Open+Sans'
-       rel='stylesheet' type='text/css'>
-<script src="/webui/static/js/jquery.min.js"></script>
+  <meta name="description" content="ASTERIX WEB PAGE" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link
+          
href='http://fonts.googleapis.com/css?family=Bitter|PT+Sans+Caption|Open+Sans'
+          rel='stylesheet' type='text/css'>
+  <script src="/webui/static/js/jquery.min.js"></script>
 
-<link href="/webui/static/css/bootstrap.min.css" rel="stylesheet"
-       type="text/css" />
-<link href="/webui/static/css/bootstrap-responsive.min.css"
-       rel="stylesheet" type="text/css" />
+  <link href="/webui/static/css/bootstrap.min.css" rel="stylesheet"
+        type="text/css" />
+  <link href="/webui/static/css/bootstrap-responsive.min.css"
+        rel="stylesheet" type="text/css" />
 
-<script src="/webui/static/js/bootstrap.min.js"></script>
+  <script src="/webui/static/js/bootstrap.min.js"></script>
 
-<link href="/webui/static/css/style.css" rel="stylesheet"
-       type="text/css" />
-<script src="/webui/static/js/jquery.json-viewer.js"></script>
-<link href="/webui/static/css/jquery.json-viewer.css" type="text/css" 
rel="stylesheet" />
+  <link href="/webui/static/css/style.css" rel="stylesheet"
+        type="text/css" />
+  <script src="/webui/static/js/jquery.json-viewer.js"></script>
+  <link href="/webui/static/css/jquery.json-viewer.css" type="text/css" 
rel="stylesheet" />
 
   <script type="text/javascript">
 $(document).ready(function() {
@@ -157,13 +157,13 @@
                 }
             }
 
-            /* Handling Pretty JSON */
+            /* Handling Pretty JSON-query result */
             var resultFormat = $('#output-format option:checked').text();
             if ( resultFormat == 'JSON (formatted)') {
               $('.result-content').each(
                   function(idx) {
                     var results = $(this).text().split('\n');
-                    $(this).css('padding-left', '20px');
+                     $(this).css('padding-left', '20px');
                     $(this).text('');
                     for (var iter1 = 0; iter1 < results.length - 1; iter1++) {
                       if (results[iter1].length < 1) {
@@ -171,10 +171,41 @@
                       }
                       var resultJSON = $.parseJSON(results[iter1]);
                       $(this).append($('<div/>').attr("id", 
"json-record"+idx+"-"+iter1));
-                      $('#json-record'+idx+"-"+iter1).jsonViewer(resultJSON, 
{collapsed: true, level: 1});
+                      $('#json-record'+idx+"-"+iter1).jsonViewer(resultJSON, 
{collapsed: true, level: 10});
                     }
                   }
                 );
+            }
+
+
+            /* Handling Pretty JSON-logical plan */
+            var planFormat = $('#plan-format option:checked').text();
+            $('.query-plan').addClass("outer");
+            if ( planFormat == 'JSON (formatted)') {
+              $('.query-plan').each(
+                  function() {
+                   var planSt = $(this).text();
+                    $(this).text('');
+                    var planJSON = $.parseJSON(planSt);
+                    $(this).append($('<div/>').attr("id", "json-queryPlan"));
+                    $('#json-queryPlan').jsonViewer(planJSON, {collapsed: 
false, level: 10});
+                  }
+              );
+            }
+
+            /* Handling Pretty JSON-optimized logical plan */
+            var optimizedPlanFormat = $('#optimizedPlanFormat 
option:checked').text();
+            $('.query-optimized-plan').addClass("outer");
+            if ( optimizedPlanFormat == 'JSON (formatted)') {
+              $('.query-optimized-plan').each(
+                  function() {
+                   var opPlanSt = $(this).text();
+                    $(this).text('');
+                    var opPlanJSON = $.parseJSON(opPlanSt);
+                    $(this).append($('<div/>').attr("id", 
"json-queryOptimizedPlan").attr("class","inner"));
+                    $('#json-queryOptimizedPlan').jsonViewer(opPlanJSON, 
{collapsed: false, level: 10});
+                  }
+              );
             }
 
 
@@ -191,106 +222,117 @@
 });
 </script>
 
-<meta charset=utf-8 />
-<title>AsterixDB Web Interface</title>
+  <meta charset=utf-8 />
+  <title>AsterixDB Web Interface</title>
 </head>
 
 <body>
-  <div class="navbar navbar-fixed-top">
-    <div class="navbar-inner">
-      <div class="container">
-        <a class="btn btn-navbar" data-toggle="collapse" 
data-target=".nav-collapse">
-          <span class="icon-bar"></span>
-          <span class="icon-bar"></span>
-          <span class="icon-bar"></span>
-        </a>
-
-        <!-- Temporary logo placeholder -->
-        <a class="brand" href="#"><img 
src="/webui/static/img/finalasterixlogo.png"></a>
-
-        <div class="nav-collapse collapse">
-          <ul class="nav">
-            <li><a href="https://asterixdb.apache.org/"; target="_blank">
-                    Open source<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
-            <li><a href="https://issues.apache.org/jira/browse/ASTERIXDB"; 
target="_blank">
-                    File issues<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
-            <li><a href="https://ci.apache.org/projects/asterixdb/index.html"; 
target="_blank">
-                    Documentation<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
-            <li><a href="https://asterixdb.apache.org/community.html"; 
target="_blank">
-                    Contact<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
-          </ul>
-        </div><!--/.nav-collapse -->
-      </div>
-    </div>
-  </div>
-
-  <div class="content">
+<div class="navbar navbar-fixed-top">
+  <div class="navbar-inner">
     <div class="container">
-      <div class="row-fluid">
+      <a class="btn btn-navbar" data-toggle="collapse" 
data-target=".nav-collapse">
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+        <span class="icon-bar"></span>
+      </a>
 
-        <div class="span6">
+      <!-- Temporary logo placeholder -->
+      <a class="brand" href="#"><img 
src="/webui/static/img/finalasterixlogo.png"></a>
 
-          <form id="queryform" class="form-horizontal" method="post">
-            <div style="margin-bottom: 1em;">
-              <label class="query">Query</label>
-              <textarea rows="10" id="qry" name="query" class="query" 
value="%s" placeholder="Type your query ..."></textarea>
-            </div>
+      <div class="nav-collapse collapse">
+        <ul class="nav">
+          <li><a href="https://asterixdb.apache.org/"; target="_blank">
+            Open source<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
+          <li><a href="https://issues.apache.org/jira/browse/ASTERIXDB"; 
target="_blank">
+            File issues<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
+          <li><a href="https://ci.apache.org/projects/asterixdb/index.html"; 
target="_blank">
+            Documentation<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
+          <li><a href="https://asterixdb.apache.org/community.html"; 
target="_blank">
+            Contact<img class="extarget" 
src="/webui/static/img/targetlink.png"/></a></li>
+        </ul>
+      </div><!--/.nav-collapse -->
+    </div>
+  </div>
+</div>
 
-            <div class="btn-group">
-              <button id="checkboxes-on" class="btn">
-                  <i id="opts" class="icon-ok" 
style="display:none;"></i>Select Options</button>
-              <button id="clear-query-button" class="btn">Clear Query</button>
-              <!-- <button id="checkboxes-off" class="btn">Clear All 
Options</button> -->
-              <button type="submit" id="run-btn" class="btn 
btn-custom-darken">Run</button>
-            </div>
+<div class="content">
+  <div class="container">
+    <div class="row-fluid">
 
-            <div>
-              <label id="query-language" class="optlabel"> Query Language:<br/>
-                <select name="query-language" class="btn">
-                  <option selected value="SQLPP">SQL++</option>
-                  <option value="AQL">AQL</option>
-                </select>
-              </label>
-              <label id="output-format" class="optlabel"> Output Format:<br/>
-                <select name="output-format" class="btn">
-                  <option selected value="CLEAN_JSON">JSON</option>
-                  <option value="CLEAN_JSON">JSON (formatted)</option>
-                  <option value="ADM">ADM</option>
-                  <option value="CSV">CSV (no header)</option>
-                  <option value="CSV-Header">CSV (with header)</option>
-                  <option value="LOSSLESS_JSON">JSON (lossless)</option>
-                </select>
-              </label>
-              <label class="optlabel"><input type="checkbox" 
name="wrapper-array" value="true" /> Wrap results in outer array</label>
-              <label class="checkbox optlabel"><input type="checkbox" 
name="print-expr-tree" value="true" /> Print parsed expressions</label>
-              <label class="checkbox optlabel"><input type="checkbox" 
name="print-rewritten-expr-tree" value="true" /> Print rewritten 
expressions</label>
-              <label class="checkbox optlabel"><input type="checkbox" 
name="print-logical-plan" value="true" /> Print logical plan</label>
-              <label class="checkbox optlabel"><input type="checkbox" 
name="print-optimized-logical-plan" value="true" /> Print optimized logical 
plan</label>
-              <label class="checkbox optlabel"><input type="checkbox" 
name="print-job" value="true" /> Print Hyracks job</label>
-              <label class="optlabel"><input type="checkbox" 
name="execute-query" value="true" checked/> Execute query</label>
-            </div>
-          </form>
-       </div>
+      <div class="span6">
 
-       <div class="span6">
-         <div class="output">
-           <label id="output-heading" class="heading">Output</label>
-           <div id="output-message" class="message">
-           </div>
-         </div>
-       </div>
+        <form id="queryform" class="form-horizontal" method="post">
+          <div style="margin-bottom: 1em;">
+            <label class="query">Query</label>
+            <textarea rows="10" id="qry" name="query" class="query" value="%s" 
placeholder="Type your query ..."></textarea>
+          </div>
 
+          <div class="btn-group">
+            <button id="checkboxes-on" class="btn">
+              <i id="opts" class="icon-ok" style="display:none;"></i>Select 
Options</button>
+            <button id="clear-query-button" class="btn">Clear Query</button>
+            <!-- <button id="checkboxes-off" class="btn">Clear All 
Options</button> -->
+            <button type="submit" id="run-btn" class="btn 
btn-custom-darken">Run</button>
+          </div>
+
+          <div>
+            <label id="query-language" class="optlabel"> Query Language:<br/>
+              <select name="query-language" class="btn btn-width">
+                <option selected value="SQLPP">SQL++</option>
+                <option value="AQL">AQL</option>
+              </select>
+            </label>
+            <label id="output-format" class="optlabel"> Output Format:<br/>
+              <select name="output-format" class="btn btn-width">
+                <option selected value="CLEAN_JSON">JSON</option>
+                <option value="CLEAN_JSON">JSON (formatted)</option>
+                <option value="ADM">ADM</option>
+                <option value="CSV">CSV (no header)</option>
+                <option value="CSV-Header">CSV (with header)</option>
+                <option value="LOSSLESS_JSON">JSON (lossless)</option>
+              </select>
+            </label>
+            <label class="optlabel"><input type="checkbox" 
name="wrapper-array" value="true" /> Wrap results in outer array</label>
+            <label class="checkbox optlabel"><input type="checkbox" 
name="print-expr-tree" value="true" /> Print parsed expressions</label>
+            <label class="checkbox optlabel"><input type="checkbox" 
name="print-rewritten-expr-tree" value="true" /> Print rewritten 
expressions</label>
+            <div class ="inline-half"><label class="checkbox optlabel"><input 
type="checkbox" name="print-logical-plan" value="true" /> Print logical 
plan</label></div><div class = "inline-half"> <label id="plan-format"> Format:
+            <select name="plan-format" class="btn inline-btn-width">
+              <option selected value="JSON">JSON</option>
+              <option value="CLEAN_JSON">JSON (formatted)</option>
+              <option value="STRING">String</option>
+            </select></label></div>
+
+            <div class ="inline-half"><label class="checkbox optlabel"><input 
type="checkbox" name="print-optimized-logical-plan" value="true" /> Print 
optimized logical plan</label></div><div class = "inline-half"> <label 
id="optimizedPlanFormat"> Format:
+            <select name="optimizedPlanFormat" class="btn inline-btn-width">
+              <option selected value="JSON">JSON</option>
+              <option value="CLEAN_JSON">JSON (formatted)</option>
+              <option value="STRING">String</option>
+            </select></label></div>
+
+            <label class="checkbox optlabel"><input type="checkbox" 
name="print-job" value="true" /> Print Hyracks job</label>
+            <label class="optlabel"><input type="checkbox" 
name="execute-query" value="true" checked/> Execute query</label>
+          </div>
+        </form>
+      </div>
+
+      <div class="span6">
+        <div class="output">
+          <label id="output-heading" class="heading">Output</label>
+          <div id="output-message" class="message">
+          </div>
+        </div>
       </div>
     </div>
-</div>
-  <div class="footer">
-    <section class="line"><hr></section>
-    <section class="content">
-      <section class="left">
-      </section>
-      <section class="right">
-      </section>
-    </section>
   </div>
+</div>
+<div class="footer">
+  <section class="line"><hr></section>
+  <section class="content">
+    <section class="left">
+    </section>
+    <section class="right">
+    </section>
+  </section>
+</div>
 </body>
 </html>
diff --git 
a/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css 
b/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
index b9b733c..8936090 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
+++ b/asterixdb/asterix-app/src/main/resources/webui/static/css/style.css
@@ -230,3 +230,29 @@
 .span6 {
     padding: 24px;
 }
+
+.inline-half {
+    display: inline-block;
+    width: 50%;
+}
+.inline-btn-width{
+    display: inline-block;
+    width: 58%;
+}
+
+.btn-width{
+    width: 30%;
+}
+.inner{
+    float : none;
+}
+
+pre.outer {
+    padding-left :20px;
+    overflow-x : scroll !important;
+    overflow-y : scroll !important;
+    word-wrap : normal !important;
+    word-break : normal !important;
+}
+
+
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
new file mode 100644
index 0000000..b26823c
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonLogicalPlanTest.java
@@ -0,0 +1 @@
+/* * Licensed to the Apache Software Foundation (ASF) under one * or more 
contributor license agreements.  See the NOTICE file * distributed with this 
work for additional information * regarding copyright ownership.  The ASF 
licenses this file * to you under the Apache License, Version 2.0 (the * 
"License"); you may not use this file except in compliance * with the License.  
You may obtain a copy of the License at * *   
http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable 
law or agreed to in writing, * software distributed under the License is 
distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 
KIND, either express or implied.  See the License for the * specific language 
governing permissions and limitations * under the License. */package 
org.apache.asterix.test.jsonplan;import 
org.apache.asterix.api.common.AsterixHyracksIntegrationUtil;import 
org.apache.asterix.api.java.AsterixJavaClient;import org.apac
 he.asterix.app.translator.DefaultStatementExecutorFactory;import 
org.apache.asterix.common.config.GlobalConfig;import 
org.apache.asterix.common.context.IStorageComponentProvider;import 
org.apache.asterix.common.dataflow.ICcApplicationContext;import 
org.apache.asterix.common.exceptions.AsterixException;import 
org.apache.asterix.compiler.provider.AqlCompilationProvider;import 
org.apache.asterix.compiler.provider.ILangCompilationProvider;import 
org.apache.asterix.compiler.provider.SqlppCompilationProvider;import 
org.apache.asterix.external.util.ExternalDataConstants;import 
org.apache.asterix.external.util.IdentitiyResolverFactory;import 
org.apache.asterix.file.StorageComponentProvider;import 
org.apache.asterix.test.base.AsterixTestHelper;import 
org.apache.asterix.test.common.TestHelper;import 
org.apache.asterix.test.runtime.HDFSCluster;import 
org.apache.asterix.translator.IStatementExecutorFactory;import 
org.apache.hyracks.api.client.IHyracksClientConnection;imp
 ort com.fasterxml.jackson.core.JsonParser;import 
com.fasterxml.jackson.databind.ObjectMapper;import org.junit.AfterClass;import 
org.junit.Assume;import org.junit.BeforeClass;import org.junit.Test;import 
org.junit.internal.AssumptionViolatedException;import 
org.junit.runner.RunWith;import org.junit.runners.Parameterized;import 
org.junit.runners.Parameterized.Parameters;import java.io.*;import 
java.util.ArrayList;import java.util.Collection;import 
java.util.logging.Logger;@RunWith(Parameterized.class)public class 
JsonLogicalPlanTest {    private static final Logger LOGGER = 
Logger.getLogger(org.apache.asterix.test.jsonplan.JsonLogicalPlanTest.class.getName());
    private static final String SEPARATOR = File.separator;    private static 
final String EXTENSION_AQL = "aql";    private static final String 
EXTENSION_SQLPP = "sqlpp";    private static final String EXTENSION_RESULT = 
"plan";    private static final String FILENAME_IGNORE = "ignore.txt";
     private static final String FILENAME_ONLY = "only.txt";    private static 
final String PATH_BASE =            "src" + SEPARATOR + "test" + SEPARATOR + 
"resources" + SEPARATOR + "optimizerts" + SEPARATOR;    private static final 
String PATH_QUERIES = PATH_BASE + "queries" + SEPARATOR;    protected static 
final String PATH_ACTUAL = "target" + File.separator + "jplantest" + SEPARATOR; 
   private static final ArrayList<String> ignore = 
AsterixTestHelper.readTestListFile(FILENAME_IGNORE, PATH_BASE);    private 
static final ArrayList<String> only = 
AsterixTestHelper.readTestListFile(FILENAME_ONLY, PATH_BASE);    protected 
static String TEST_CONFIG_FILE_NAME = "asterix-build-configuration.xml";    
private static final ILangCompilationProvider aqlCompilationProvider = new 
AqlCompilationProvider();    private static final ILangCompilationProvider 
sqlppCompilationProvider = new SqlppCompilationProvider();    protected static 
ILangCompilationProvider extensionLangCompila
 tionProvider = null;    protected static IStatementExecutorFactory 
statementExecutorFactory = new DefaultStatementExecutorFactory();    protected 
static IStorageComponentProvider storageComponentProvider = new 
StorageComponentProvider();    protected static AsterixHyracksIntegrationUtil 
integrationUtil = new AsterixHyracksIntegrationUtil();    @BeforeClass    
public static void setUp() throws Exception {        
System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, TEST_CONFIG_FILE_NAME);   
     final File outdir = new File(PATH_ACTUAL);        outdir.mkdirs();        
HDFSCluster.getInstance().setup();        integrationUtil.init(true);        // 
Set the node resolver to be the identity resolver that expects node names       
 // to be node controller ids; a valid assumption in test environment.        
System.setProperty(ExternalDataConstants.NODE_RESOLVER_FACTORY_PROPERTY,        
        IdentitiyResolverFactory.class.getName());    }    @AfterClass    p
 ublic static void tearDown() throws Exception {        File outdir = new 
File(PATH_ACTUAL);        File[] files = outdir.listFiles();        if (files 
== null || files.length == 0) {            outdir.delete();        }        
HDFSCluster.getInstance().cleanup();        integrationUtil.deinit(true);    }  
  private static void suiteBuildPerFile(File file, Collection<Object[]> 
testArgs, String path) {        if (file.isDirectory() && 
!file.getName().startsWith(".")) {            for (File innerfile : 
file.listFiles()) {                String subdir = innerfile.isDirectory() ? 
path + innerfile.getName() + SEPARATOR : path;                
suiteBuildPerFile(innerfile, testArgs, subdir);            }        }        if 
(file.isFile() && (file.getName().endsWith(EXTENSION_AQL) || 
file.getName().endsWith(EXTENSION_SQLPP))) {            String resultFileName = 
AsterixTestHelper.extToResExt(file.getName(), EXTENSION_RESULT);            
File actualFile = new File(
 PATH_ACTUAL + SEPARATOR + path + resultFileName);            testArgs.add(new 
Object[] { file, actualFile });        }    }    @Parameters(name = 
"JsonLogicalPlanTest {index}: {0}")    public static Collection<Object[]> 
tests() {        Collection<Object[]> testArgs = new ArrayList<>();        if 
(only.isEmpty()) {            suiteBuildPerFile(new File(PATH_QUERIES), 
testArgs, "");        } else {            for (String path : only) {            
    suiteBuildPerFile(new File(PATH_QUERIES + path), testArgs,                  
      path.lastIndexOf(SEPARATOR) < 0 ? "" : path.substring(0, 
path.lastIndexOf(SEPARATOR) + 1));            }        }        return 
testArgs;    }    private final File actualFile;    private final File 
queryFile;    public JsonLogicalPlanTest(final File queryFile, final File 
actualFile) {        this.queryFile = queryFile;        this.actualFile = 
actualFile;    }    @Test    public void test() throws Exception {        try
  {            String queryFileShort =                    
queryFile.getPath().substring(PATH_QUERIES.length()).replace(SEPARATOR.charAt(0),
 '/');            if (!only.isEmpty()) {                boolean toRun = 
TestHelper.isInPrefixList(only, queryFileShort);                if (!toRun) {   
                 LOGGER.info("SKIP TEST: \"" + queryFile.getPath()              
              + "\" \"only.txt\" not empty and not in \"only.txt\".");          
      }                Assume.assumeTrue(toRun);            }            
boolean skipped = TestHelper.isInPrefixList(ignore, queryFileShort);            
if (skipped) {                LOGGER.info("SKIP TEST: \"" + queryFile.getPath() 
+ "\" in \"ignore.txt\".");            }            
Assume.assumeTrue(!skipped);            LOGGER.info("RUN TEST: \"" + 
queryFile.getPath() + "\"");            Reader query = new BufferedReader(new 
InputStreamReader(new FileInputStream(queryFile), "UTF-8"));            // 
Forces the c
 reation of actualFile.            actualFile.getParentFile().mkdirs();         
   PrintWriter plan = new PrintWriter(actualFile);            
ILangCompilationProvider provider =                    
queryFile.getName().endsWith("aql") ? aqlCompilationProvider : 
sqlppCompilationProvider;            if (extensionLangCompilationProvider != 
null) {                provider = extensionLangCompilationProvider;            
}            IHyracksClientConnection hcc = 
integrationUtil.getHyracksClientConnection();            AsterixJavaClient 
asterix =                    new AsterixJavaClient((ICcApplicationContext) 
integrationUtil.cc.getApplicationContext(), hcc,                            
query, plan, provider, statementExecutorFactory, storageComponentProvider);     
       try {                asterix.compile(true, false, true, false, false, 
false, false);            } catch (AsterixException e) {                
plan.close();                query.close();             
    throw new Exception("Compile ERROR for " + queryFile + ": " + 
e.getMessage(), e);            }            plan.close();            
query.close();            BufferedReader readerActual =                    new 
BufferedReader(new InputStreamReader(new FileInputStream(actualFile), 
"UTF-8"));            String lineActual,objectActual="";            boolean 
firstPlan = false;            while((lineActual = 
readerActual.readLine())!=null){                if(lineActual.contains("--")){  
                  if(firstPlan){                        break;                  
  }                    firstPlan = true;                }                else { 
                   objectActual = objectActual + lineActual;                }   
         }            try {                final JsonParser parser = new 
ObjectMapper().getJsonFactory()                        
.createJsonParser(objectActual);                while (parser.nextToken() != 
null) {                }    
         } finally {                readerActual.close();            }        } 
catch (Exception e) {            if (!(e instanceof 
AssumptionViolatedException)) {                LOGGER.severe("Test \"" + 
queryFile.getPath() + "\" FAILED!");                throw new Exception("Test 
\"" + queryFile.getPath() + "\" FAILED!", e);            } else {               
 throw e;            }        }    }}
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
new file mode 100644
index 0000000..ad466c3
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/jsonplan/JsonOptimizedLogicalPlanTest.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.test.jsonplan;
+
+import org.apache.asterix.api.common.AsterixHyracksIntegrationUtil;
+import org.apache.asterix.api.java.AsterixJavaClient;
+import org.apache.asterix.app.translator.DefaultStatementExecutorFactory;
+import org.apache.asterix.common.config.GlobalConfig;
+import org.apache.asterix.common.context.IStorageComponentProvider;
+import org.apache.asterix.common.dataflow.ICcApplicationContext;
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.compiler.provider.AqlCompilationProvider;
+import org.apache.asterix.compiler.provider.ILangCompilationProvider;
+import org.apache.asterix.compiler.provider.SqlppCompilationProvider;
+import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.asterix.external.util.IdentitiyResolverFactory;
+import org.apache.asterix.file.StorageComponentProvider;
+import org.apache.asterix.test.base.AsterixTestHelper;
+import org.apache.asterix.test.common.TestHelper;
+import org.apache.asterix.test.runtime.HDFSCluster;
+import org.apache.asterix.translator.IStatementExecutorFactory;
+import org.apache.hyracks.api.client.IHyracksClientConnection;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+
+
+
+
+
+@RunWith(Parameterized.class)
+public class JsonOptimizedLogicalPlanTest {
+
+    private static final Logger LOGGER = 
Logger.getLogger(org.apache.asterix.test.jsonplan.JsonOptimizedLogicalPlanTest.class.getName());
+
+    private static final String SEPARATOR = File.separator;
+    private static final String EXTENSION_AQL = "aql";
+    private static final String EXTENSION_SQLPP = "sqlpp";
+    private static final String EXTENSION_RESULT = "plan";
+    private static final String FILENAME_IGNORE = "ignore.txt";
+    private static final String FILENAME_ONLY = "only.txt";
+    private static final String PATH_BASE =
+            "src" + SEPARATOR + "test" + SEPARATOR + "resources" + SEPARATOR + 
"optimizerts" + SEPARATOR;
+    private static final String PATH_QUERIES = PATH_BASE + "queries" + 
SEPARATOR;
+    protected static final String PATH_ACTUAL = "target" + File.separator + 
"joptplantest" + SEPARATOR;
+
+    private static final ArrayList<String> ignore = 
AsterixTestHelper.readTestListFile(FILENAME_IGNORE, PATH_BASE);
+    private static final ArrayList<String> only = 
AsterixTestHelper.readTestListFile(FILENAME_ONLY, PATH_BASE);
+    protected static String TEST_CONFIG_FILE_NAME = 
"asterix-build-configuration.xml";
+    private static final ILangCompilationProvider aqlCompilationProvider = new 
AqlCompilationProvider();
+    private static final ILangCompilationProvider sqlppCompilationProvider = 
new SqlppCompilationProvider();
+    protected static ILangCompilationProvider extensionLangCompilationProvider 
= null;
+    protected static IStatementExecutorFactory statementExecutorFactory = new 
DefaultStatementExecutorFactory();
+    protected static IStorageComponentProvider storageComponentProvider = new 
StorageComponentProvider();
+
+    protected static AsterixHyracksIntegrationUtil integrationUtil = new 
AsterixHyracksIntegrationUtil();
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, 
TEST_CONFIG_FILE_NAME);
+        final File outdir = new File(PATH_ACTUAL);
+        outdir.mkdirs();
+
+        HDFSCluster.getInstance().setup();
+
+        integrationUtil.init(true);
+        // Set the node resolver to be the identity resolver that expects node 
names
+        // to be node controller ids; a valid assumption in test environment.
+        
System.setProperty(ExternalDataConstants.NODE_RESOLVER_FACTORY_PROPERTY,
+                IdentitiyResolverFactory.class.getName());
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        File outdir = new File(PATH_ACTUAL);
+        File[] files = outdir.listFiles();
+        if (files == null || files.length == 0) {
+            outdir.delete();
+        }
+
+        HDFSCluster.getInstance().cleanup();
+
+        integrationUtil.deinit(true);
+    }
+
+    private static void suiteBuildPerFile(File file, Collection<Object[]> 
testArgs, String path) {
+        if (file.isDirectory() && !file.getName().startsWith(".")) {
+            for (File innerfile : file.listFiles()) {
+                String subdir = innerfile.isDirectory() ? path + 
innerfile.getName() + SEPARATOR : path;
+                suiteBuildPerFile(innerfile, testArgs, subdir);
+            }
+        }
+        if (file.isFile() && (file.getName().endsWith(EXTENSION_AQL) || 
file.getName().endsWith(EXTENSION_SQLPP))) {
+            String resultFileName = 
AsterixTestHelper.extToResExt(file.getName(), EXTENSION_RESULT);
+            File actualFile = new File(PATH_ACTUAL + SEPARATOR + path + 
resultFileName);
+            testArgs.add(new Object[] { file, actualFile });
+        }
+    }
+
+    @Parameters(name = "JsonLogicalPlanTest {index}: {0}")
+    public static Collection<Object[]> tests() {
+        Collection<Object[]> testArgs = new ArrayList<>();
+        if (only.isEmpty()) {
+            suiteBuildPerFile(new File(PATH_QUERIES), testArgs, "");
+        } else {
+            for (String path : only) {
+                suiteBuildPerFile(new File(PATH_QUERIES + path), testArgs,
+                        path.lastIndexOf(SEPARATOR) < 0 ? "" : 
path.substring(0, path.lastIndexOf(SEPARATOR) + 1));
+            }
+        }
+        return testArgs;
+    }
+
+    private final File actualFile;
+    private final File queryFile;
+
+    public JsonOptimizedLogicalPlanTest(final File queryFile, final File 
actualFile) {
+        this.queryFile = queryFile;
+        this.actualFile = actualFile;
+    }
+
+    @Test
+    public void test() throws Exception {
+        try {
+            String queryFileShort =
+                    
queryFile.getPath().substring(PATH_QUERIES.length()).replace(SEPARATOR.charAt(0),
 '/');
+            if (!only.isEmpty()) {
+                boolean toRun = TestHelper.isInPrefixList(only, 
queryFileShort);
+                if (!toRun) {
+                    LOGGER.info("SKIP TEST: \"" + queryFile.getPath()
+                            + "\" \"only.txt\" not empty and not in 
\"only.txt\".");
+                }
+                Assume.assumeTrue(toRun);
+            }
+            boolean skipped = TestHelper.isInPrefixList(ignore, 
queryFileShort);
+            if (skipped) {
+                LOGGER.info("SKIP TEST: \"" + queryFile.getPath() + "\" in 
\"ignore.txt\".");
+            }
+            Assume.assumeTrue(!skipped);
+
+            LOGGER.info("RUN TEST: \"" + queryFile.getPath() + "\"");
+            Reader query = new BufferedReader(new InputStreamReader(new 
FileInputStream(queryFile), "UTF-8"));
+
+            // Forces the creation of actualFile.
+            actualFile.getParentFile().mkdirs();
+
+            PrintWriter plan = new PrintWriter(actualFile);
+            ILangCompilationProvider provider =
+                    queryFile.getName().endsWith("aql") ? 
aqlCompilationProvider : sqlppCompilationProvider;
+            if (extensionLangCompilationProvider != null) {
+                provider = extensionLangCompilationProvider;
+            }
+            IHyracksClientConnection hcc = 
integrationUtil.getHyracksClientConnection();
+            AsterixJavaClient asterix =
+                    new AsterixJavaClient((ICcApplicationContext) 
integrationUtil.cc.getApplicationContext(), hcc,
+                            query, plan, provider, statementExecutorFactory, 
storageComponentProvider);
+            try {
+                asterix.compile(true, false, false, true, false, false, false);
+
+            } catch (AsterixException e) {
+                plan.close();
+                query.close();
+                throw new Exception("Compile ERROR for " + queryFile + ": " + 
e.getMessage(), e);
+            }
+            plan.close();
+            query.close();
+
+            BufferedReader readerActual =
+                    new BufferedReader(new InputStreamReader(new 
FileInputStream(actualFile), "UTF-8"));
+            String lineActual,objectActual="";
+            boolean firstPlan = false;
+            while((lineActual = readerActual.readLine())!=null){
+                if(lineActual.contains("--")){
+                    if(firstPlan){
+                        break;
+                    }
+                    firstPlan = true;
+
+                }
+                else {
+                    objectActual = objectActual + lineActual;
+                }
+            }
+
+            try {
+                final JsonParser parser = new ObjectMapper().getJsonFactory()
+                        .createJsonParser(objectActual);
+                while (parser.nextToken() != null) {
+                }
+            } finally {
+                readerActual.close();
+            }
+
+
+        } catch (Exception e) {
+            if (!(e instanceof AssumptionViolatedException)) {
+                LOGGER.severe("Test \"" + queryFile.getPath() + "\" FAILED!");
+                throw new Exception("Test \"" + queryFile.getPath() + "\" 
FAILED!", e);
+            } else {
+                throw e;
+            }
+        }
+    }
+}
+
+
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
index 4686f32..1b23677 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/AbstractLogicalOperator.java
@@ -18,19 +18,9 @@
  */
 package org.apache.hyracks.algebricks.core.algebra.operators.logical;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.IHyracksJobBuilder;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.IPhysicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.base.*;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.IPhysicalPropertiesVector;
 import 
org.apache.hyracks.algebricks.core.algebra.properties.PhysicalRequirements;
@@ -40,6 +30,11 @@
 import org.apache.hyracks.algebricks.core.algebra.typing.OpRefTypeEnvPointer;
 import 
org.apache.hyracks.algebricks.core.algebra.typing.PropagatingTypeEnvironment;
 import org.apache.hyracks.algebricks.core.jobgen.impl.JobGenContext;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 public abstract class AbstractLogicalOperator implements ILogicalOperator {
 
@@ -65,10 +60,16 @@
     protected IPhysicalOperator physicalOperator;
     private final Map<String, Object> annotations = new HashMap<>();
     private boolean bJobGenEnabled = true;
+    private int operatorID=0;
 
     protected final List<Mutable<ILogicalOperator>> inputs;
     protected List<LogicalVariable> schema;
-
+public void setOperatorID(int id){
+        operatorID = id;
+}
+public int getOperatorID(){
+    return operatorID;
+    }
     public AbstractLogicalOperator() {
         inputs = new ArrayList<>();
     }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
index f8d0a50..bc98b32 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/ALogicalPlanImpl.java
@@ -18,9 +18,6 @@
  */
 package org.apache.hyracks.algebricks.core.algebra.plan;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -28,6 +25,9 @@
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class ALogicalPlanImpl implements ILogicalPlan {
     private List<Mutable<ILogicalOperator>> roots;
 
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
index 2139627..5243f64 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitor.java
@@ -18,8 +18,6 @@
  */
 package org.apache.hyracks.algebricks.core.algebra.prettyprint;
 
-import java.util.List;
-
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
@@ -27,46 +25,13 @@
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestMapOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DistributeResultOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.IndexInsertDeleteUpsertOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.IntersectOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestMapOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterUnnestOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.MaterializeOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.ReplicateOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.RunningAggregateOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.ScriptOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SinkOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SplitOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.TokenizeOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteResultOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
 
+import java.util.List;
+
 public class LogicalOperatorPrettyPrintVisitor implements 
ILogicalOperatorVisitor<Void, Integer> {
 
     ILogicalExpressionVisitor<String, Integer> exprVisitor;
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
new file mode 100644
index 0000000..183d3e5
--- /dev/null
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/LogicalOperatorPrettyPrintVisitorJson.java
@@ -0,0 +1,709 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.algebricks.core.algebra.prettyprint;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteUpsertOperator.Kind;
+import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionVisitor;
+import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
+
+import java.util.List;
+
+public class LogicalOperatorPrettyPrintVisitorJson implements 
ILogicalOperatorVisitor<Void,Integer> {
+    ILogicalExpressionVisitor<String, Integer> exprVisitor;
+    AlgebricksAppendable buffer;
+
+    public LogicalOperatorPrettyPrintVisitorJson(Appendable app) {
+        this(new AlgebricksAppendable(app), new 
LogicalExpressionPrettyPrintVisitor());
+    }
+
+    public LogicalOperatorPrettyPrintVisitorJson(AlgebricksAppendable buffer) {
+        this(buffer, new LogicalExpressionPrettyPrintVisitor());
+    }
+
+    public LogicalOperatorPrettyPrintVisitorJson(AlgebricksAppendable buffer, 
ILogicalExpressionVisitor<String, Integer> exprVisitor) {
+        reset(buffer);
+        this.exprVisitor = exprVisitor;
+    }
+
+    public AlgebricksAppendable reset(AlgebricksAppendable buffer) {
+        AlgebricksAppendable old = this.buffer;
+        this.buffer = buffer;
+        return old;
+    }
+
+    public AlgebricksAppendable get() {
+        return buffer;
+    }
+
+    @Override
+    public String toString() {
+        return buffer.toString();
+    }
+
+    CharSequence str(Object o) {
+        return String.valueOf(o);
+    }
+
+    @Override
+    public Void visitAggregateOperator(AggregateOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"aggregate\"");
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\" :[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+
+        return null;
+    }
+
+    @Override
+    public Void visitRunningAggregateOperator(RunningAggregateOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"running-aggregate\"");
+        if(op.getVariables().size() > 0) {
+                addIndent(0).append(",\n");
+                addIndent(indent).append("\"variables\" :[");
+                boolean first = true;
+                for (LogicalVariable v : op.getVariables()){
+                    if(!first)
+                        buffer.append(",");
+                    buffer.append("\""+str(v)+"\"");
+                    first=false;
+                }
+                buffer.append("]");
+            }
+            if(op.getExpressions().size()>0) {
+                addIndent(0).append(",\n");
+                pprintExprList(op.getExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitEmptyTupleSourceOperator(EmptyTupleSourceOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"empty-tuple-source\"");
+        return null;
+    }
+
+
+    @Override
+    public Void visitGroupByOperator(GroupByOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"group-by\"" );
+
+        if(op.isGroupAll()) {
+            buffer.append(",\n");
+            addIndent(indent).append( "\"option\":\"all\"");
+        }
+            if(op.getGroupByList().size()>0) {
+                buffer.append(",\n");
+                addIndent(indent).append("\"group-by-list\":");
+                pprintVeList(op.getGroupByList(), indent);
+        }
+        if(op.getDecorList().size()>0) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"decor-list\":");
+            pprintVeList(op.getDecorList(), indent);
+        }
+        if(op.getNestedPlans().size()>0) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"subplan\":");
+            PlanPrettyPrinter.reset(op);
+            printNestedPlans(op, indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDistinctOperator(DistinctOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"distinct\"");
+        if(op.getExpressions().size()>0) {
+            addIndent(0).append(",\n");
+            pprintExprList(op.getExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitInnerJoinOperator(InnerJoinOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"join\",\n");
+        
addIndent(indent).append("\"condition\":"+"\""+op.getCondition().getValue().accept(exprVisitor,
 indent)+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitLeftOuterJoinOperator(LeftOuterJoinOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"left-outer-join\",\n");
+        
addIndent(indent).append("\"condition\":"+"\""+op.getCondition().getValue().accept(exprVisitor,
 indent)+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op, 
Integer indent)
+            throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"nested-tuple-source\"");
+        return null;
+    }
+
+    @Override
+    public Void visitOrderOperator(OrderOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"order\"");
+        for (Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>> p : 
op.getOrderExpressions()) {
+            buffer.append(",\n");
+            if (op.getTopK() != -1) {
+                addIndent(indent).append("\"topK\":\"" + op.getTopK() + 
"\",\n");
+            }
+            String fst = getOrderString(p.first);
+            addIndent(indent).append("\"first\":" + fst + ",\n");
+            
addIndent(indent).append("\"second\":\""+p.second.getValue().accept(exprVisitor,
 indent).replace('"',' ') + "\"");
+        }
+        return null;
+    }
+
+    private String getOrderString(OrderOperator.IOrder first) {
+        switch (first.getKind()) {
+            case ASC:
+                return "\"ASC\"";
+            case DESC:
+                return "\"DESC\"";
+            default:
+                return first.getExpressionRef().toString();
+        }
+    }
+
+    @Override
+    public Void visitAssignOperator(AssignOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"assign\"");
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if(op.getExpressions().size()>0) {
+            addIndent(0).append(",\n");
+            pprintExprList(op.getExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitWriteOperator(WriteOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"write\"");
+        if(op.getExpressions().size()>0) {
+            addIndent(0).append(",\n");
+            pprintExprList(op.getExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitDistributeResultOperator(DistributeResultOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"distribute-result\"");
+        if(op.getExpressions().size()>0) {
+            addIndent(0).append(",\n");
+            pprintExprList(op.getExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitWriteResultOperator(WriteResultOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"load\",\n");
+        addIndent(indent).append(str(op.getDataSource())).append("\"from\":")
+                
.append(op.getPayloadExpression().getValue().accept(exprVisitor, indent)+",\n");
+        addIndent(indent).append("\"partitioned-by\":{");
+        pprintExprList(op.getKeyExpressions(), indent);
+        addIndent(indent).append("}");
+        return null;
+    }
+
+    @Override
+    public Void visitSelectOperator(SelectOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"select\",\n");
+        
addIndent(indent).append("\"expressions\":\""+op.getCondition().getValue().accept(exprVisitor,
 indent).replace('"',' ')+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitProjectOperator(ProjectOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"project\"");
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitSubplanOperator(SubplanOperator op, Integer indent) 
throws AlgebricksException {
+        if(!op.getNestedPlans().isEmpty()) {
+            addIndent(indent).append("\"subplan\":");
+            PlanPrettyPrinter.reset(op);
+            printNestedPlans(op, indent);
+        }
+        return null;
+    }
+    @Override
+    public Void visitUnionOperator(UnionAllOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"union\"");
+        for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> v : 
op.getVariableMappings()) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"values\":[" +"\""+ v.first + "\"," + 
"\""+v.second + "\"," + "\""+v.third + "\"]");
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitIntersectOperator(IntersectOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"intersect\",\n");
+
+        addIndent(indent).append("\"output-variables\":[");
+        for (int i = 0; i < op.getOutputVars().size(); i++) {
+            if (i > 0) {
+                buffer.append(", ");
+            }
+            buffer.append("\""+str(op.getOutputVars().get(i))+"\"");
+        }
+        buffer.append("],");
+        addIndent(indent).append("\"input_variables\":[");
+        for (int i = 0; i < op.getNumInput(); i++) {
+            if (i > 0) {
+                buffer.append(",\n");
+            }
+            buffer.append("[");
+            for (int j = 0; j < op.getInputVariables(i).size(); j++) {
+                if (j > 0) {
+                    buffer.append(", ");
+                }
+                buffer.append("\""+str(op.getInputVariables(i).get(j))+"\"");
+            }
+            buffer.append(']');
+        }
+        buffer.append("]");
+        return null;
+    }
+
+    @Override
+    public Void visitUnnestOperator(UnnestOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"unnest\"");
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\" :[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if (op.getPositionalVariable() != null) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"position\":\"" + 
op.getPositionalVariable()+"\"");
+        }
+        buffer.append(",\n");
+        
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
 indent).replace('"',' ')+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitLeftOuterUnnestOperator(LeftOuterUnnestOperator op, 
Integer indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"outer-unnest\",\n");
+        addIndent(indent).append("\"variables\":[\""+ op.getVariable()+"\"]");
+        if (op.getPositionalVariable() != null) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"position\":" + 
op.getPositionalVariable());
+        }
+        buffer.append(",\n");
+        
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
 indent).replace('"',' ')+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitUnnestMapOperator(UnnestMapOperator op, Integer indent) 
throws AlgebricksException {
+        return printAbstractUnnestMapOperator(op, indent, "unnest-map");
+    }
+
+    @Override
+    public Void visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, 
Integer indent)
+            throws AlgebricksException {
+        return printAbstractUnnestMapOperator(op, indent, 
"left-outer-unnest-map");
+    }
+
+    private Void printAbstractUnnestMapOperator(AbstractUnnestMapOperator op, 
Integer indent, String opSignature)
+            throws AlgebricksException {
+        AlgebricksAppendable plan = 
addIndent(indent).append("\"operator\":\""+opSignature + "\"");
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        buffer.append(",\n");
+        
addIndent(indent).append("\"expressions\":\""+op.getExpressionRef().getValue().accept(exprVisitor,
 indent).replace('"',' ')+"\"");
+        appendFilterInformation(plan, op.getMinFilterVars(), 
op.getMaxFilterVars(),indent);
+        return null;
+    }
+
+    @Override
+    public Void visitDataScanOperator(DataSourceScanOperator op, Integer 
indent) throws AlgebricksException {
+        AlgebricksAppendable plan = addIndent(indent).append(
+                "\"operator\":\"data-scan\"");
+        if(op.getProjectVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"project-variables\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getProjectVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if(op.getVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+            if(op.getDataSource()!=null){
+                addIndent(0).append(",\n");
+                
addIndent(indent).append("\"data-source\":\""+op.getDataSource()+"\"");
+            }
+        }
+        appendFilterInformation(plan, op.getMinFilterVars(), 
op.getMaxFilterVars(),indent);
+        return null;
+    }
+
+    private Void appendFilterInformation(AlgebricksAppendable plan, 
List<LogicalVariable> minFilterVars,
+                                         List<LogicalVariable> maxFilterVars, 
Integer indent) throws AlgebricksException {
+        if (minFilterVars != null || maxFilterVars != null) {
+            plan.append(",\n");
+            addIndent(indent);
+            plan.append("\"with-filter-on\":{");
+        }
+        if (minFilterVars != null) {
+            buffer.append("\n");
+            addIndent(indent).append("\"min\":[");
+            boolean first = true;
+            for (LogicalVariable v : minFilterVars){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if(minFilterVars != null && maxFilterVars != null){
+            buffer.append(",");
+        }
+        if (maxFilterVars != null) {
+            buffer.append("\n");
+            addIndent(indent).append("\"max\":[");
+            boolean first = true;
+            for (LogicalVariable v : maxFilterVars){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if (minFilterVars != null || maxFilterVars != null) {
+            plan.append("\n");
+            addIndent(indent).append("}");
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitLimitOperator(LimitOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"limit\",\n");
+        
addIndent(indent).append("\"value\":\""+op.getMaxObjects().getValue().accept(exprVisitor,
 indent)+"\"");
+        ILogicalExpression offset = op.getOffset().getValue();
+        if (offset != null) {
+            buffer.append(",\n");
+            
addIndent(indent).append("\"offset\":\""+offset.accept(exprVisitor, 
indent)+"\"");
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitExchangeOperator(ExchangeOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"exchange\"");
+        return null;
+    }
+
+    @Override
+    public Void visitScriptOperator(ScriptOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"script\"");
+        if(op.getInputVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"in\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getInputVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if(op.getOutputVariables().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"out\":[");
+            boolean first = true;
+            for (LogicalVariable v : op.getOutputVariables()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitReplicateOperator(ReplicateOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"replicate\"");
+        return null;
+    }
+
+    @Override
+    public Void visitSplitOperator(SplitOperator op, Integer indent) throws 
AlgebricksException {
+        Mutable<ILogicalExpression> branchingExpression = 
op.getBranchingExpression();
+        addIndent(indent).append("\"operator\":\"split\",\n");
+        
addIndent(indent).append("\""+branchingExpression.getValue().accept(exprVisitor,
 indent)+"\"");
+        return null;
+    }
+
+    @Override
+    public Void visitMaterializeOperator(MaterializeOperator op, Integer 
indent) throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"materialize\"");
+        return null;
+    }
+
+    @Override
+    public Void visitInsertDeleteUpsertOperator(InsertDeleteUpsertOperator op, 
Integer indent)
+            throws AlgebricksException {
+        String header = 
"\"operator\":\""+getIndexOpString(op.getOperation())+"\",\n";
+        addIndent(indent).append(header);
+        
addIndent(indent).append(str("\"data-source\":\""+op.getDataSource()+"\",\n"));
+        addIndent(indent).append("\"from-record\":\"")
+                
.append(op.getPayloadExpression().getValue().accept(exprVisitor, indent)+"\"");
+        if (op.getAdditionalNonFilteringExpressions() != null) {
+            buffer.append(",\n\"meta\":\"");
+            pprintExprList(op.getAdditionalNonFilteringExpressions(), 0);
+            buffer.append("\"");
+        }
+        buffer.append(",\n");
+        addIndent(indent).append("\"partitioned-by\":{");
+        pprintExprList(op.getPrimaryKeyExpressions(), 0);
+        buffer.append("}");
+        if (op.getOperation() == Kind.UPSERT) {
+            addIndent(indent).append(",\n\"out\":{\n");
+            addIndent(indent).append("\"record-before-upsert\":\"" + 
op.getBeforeOpRecordVar()+"\"");
+            if((op.getBeforeOpAdditionalNonFilteringVars() != null)){
+                buffer.append(",\n");
+                addIndent(indent).append("\"additional-before-upsert\":\"" + 
op.getBeforeOpAdditionalNonFilteringVars()+"\"");
+            }
+            addIndent(indent).append("}");
+        }
+        if (op.isBulkload()) {
+            buffer.append(",\n");
+            addIndent(indent).append("\"bulkload\":\"true\"");
+        }
+        return null;
+    }
+
+    @Override
+    public Void 
visitIndexInsertDeleteUpsertOperator(IndexInsertDeleteUpsertOperator op, 
Integer indent)
+            throws AlgebricksException {
+        String header = getIndexOpString(op.getOperation());
+        addIndent(indent).append("\"operator\":\""+header+"\",\n");
+        addIndent(indent).append("\"index\":\""+op.getIndexName()+"\",\n");
+        addIndent(indent).append("\"on\":\"")
+                .append(str(op.getDataSourceIndex().getDataSource())+"\",\n");
+        addIndent(indent).append("\"from\":{");
+
+        if (op.getOperation() == Kind.UPSERT) {
+
+            addIndent(indent).append("[\"replace\":\"");
+            pprintExprList(op.getPrevSecondaryKeyExprs(), 0);
+            buffer.append("\",\n");
+            addIndent(indent).append("\"with\":\"");
+            pprintExprList(op.getSecondaryKeyExpressions(), 0);
+            buffer.append("\"}");
+        } else {
+            pprintExprList(op.getSecondaryKeyExpressions(), 0);
+        }
+        buffer.append("\n");
+        addIndent(indent).append("}");
+        if (op.isBulkload()) {
+            buffer.append(",\n");
+            buffer.append("\"bulkload\":\"true\"");
+        }
+        return null;
+    }
+
+    public String getIndexOpString(Kind opKind) {
+        switch (opKind) {
+            case DELETE:
+                return "delete-from";
+            case INSERT:
+                return "insert-into";
+            case UPSERT:
+                return "upsert-into";
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitTokenizeOperator(TokenizeOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\"tokenize\"");
+        if(op.getTokenizeVars().size() > 0) {
+            addIndent(0).append(",\n");
+            addIndent(indent).append("\"variables\" :[");
+            boolean first = true;
+            for (LogicalVariable v : op.getTokenizeVars()){
+                if(!first)
+                    buffer.append(",");
+                buffer.append("\""+str(v)+"\"");
+                first=false;
+            }
+            buffer.append("]");
+        }
+        if(op.getSecondaryKeyExpressions().size()>0) {
+            addIndent(0).append(",\n");
+            pprintExprList(op.getSecondaryKeyExpressions(), indent);
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitSinkOperator(SinkOperator op, Integer indent) throws 
AlgebricksException {
+        addIndent(indent).append("\"operator\":\"sink\"");
+        return null;
+    }
+
+    @Override
+    public Void visitDelegateOperator(DelegateOperator op, Integer indent) 
throws AlgebricksException {
+        addIndent(indent).append("\"operator\":\""+op.toString()+"\"");
+        return null;
+    }
+
+    protected AlgebricksAppendable addIndent(int level) throws 
AlgebricksException {
+        for (int i = 0; i < level; ++i) {
+            buffer.append(' ');
+        }
+        return buffer;
+    }
+
+    protected void printNestedPlans(AbstractOperatorWithNestedPlans op, 
Integer indent) throws AlgebricksException {
+        PlanPrettyPrinter.reset(op);
+        buffer.append("[\n");
+        boolean first=true;
+        for (ILogicalPlan p : op.getNestedPlans()) {
+            if(!first)
+                buffer.append(",");
+            PlanPrettyPrinter.printPlanJson(p, this, indent+4);
+            first=false;
+
+        }
+        addIndent(indent).append("]");
+    }
+    //Done--Look for exprRef
+    protected void pprintExprList(List<Mutable<ILogicalExpression>> 
expressions, Integer indent)
+            throws AlgebricksException {
+        addIndent(indent);
+        buffer.append("\"expressions\":\"");
+        boolean first = true;
+        for (Mutable<ILogicalExpression> exprRef : expressions) {
+            if (first) {
+                first = false;
+            } else {
+                buffer.append(", ");
+            }
+            buffer.append(exprRef.getValue().accept(exprVisitor, 
indent).replace('"',' '));
+        }
+        buffer.append("\"");
+    }
+
+    protected void pprintVeList(List<Pair<LogicalVariable, 
Mutable<ILogicalExpression>>> vePairList, Integer indent)
+            throws AlgebricksException {
+        buffer.append("[");
+        boolean fst = true;
+        for (Pair<LogicalVariable, Mutable<ILogicalExpression>> ve : 
vePairList) {
+            if (fst) {
+                fst = false;
+            } else {
+                buffer.append(",");
+            }
+            if (ve.first != null) {
+                
buffer.append("{\"variable\":\""+ve.first.toString().replace('"',' ') + "\"," 
+"\"expression\":\"" + ve.second.toString().replace('"',' ')+"\"}");
+            } else {
+                
buffer.append("{\"expression\":\""+ve.second.getValue().accept(exprVisitor, 
indent).replace('"',' ')+"\"}");
+            }
+        }
+        buffer.append("]");
+    }
+
+}
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
index 9a55f11..f3be9a2 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/prettyprint/PlanPrettyPrinter.java
@@ -27,6 +27,13 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 
 public class PlanPrettyPrinter {
+    public static int operatorID=0;
+    public static void printPlanJson(ILogicalPlan plan, 
LogicalOperatorPrettyPrintVisitorJson pvisitor, int indent)
+            throws AlgebricksException {
+        for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+            printOperatorJson((AbstractLogicalOperator) root.getValue(), 
pvisitor, indent);
+        }
+    }
     public static void printPlan(ILogicalPlan plan, 
LogicalOperatorPrettyPrintVisitor pvisitor, int indent)
             throws AlgebricksException {
         for (Mutable<ILogicalOperator> root : plan.getRoots()) {
@@ -59,7 +66,51 @@
             printOperator((AbstractLogicalOperator) i.getValue(), pvisitor, 
indent + 2);
         }
     }
+    public static void printOperatorJson(AbstractLogicalOperator op, 
LogicalOperatorPrettyPrintVisitorJson pvisitor, int indent)
+            throws AlgebricksException {
+        final AlgebricksAppendable out = pvisitor.get();
+        pad(out, indent);
+        // append(out,"{\"Operator\":\"");
+        appendln(out,"{");
+        op.accept(pvisitor, indent+1);
+        indent++;
+        appendln(out,",");
+        pad(out, indent);
+        if(op.getOperatorID()==0){
+            op.setOperatorID(operatorID);
+            operatorID++;
+        }
+        append(out,"\"operator-id\":"+op.getOperatorID());
 
+        IPhysicalOperator pOp = op.getPhysicalOperator();
+        if(pOp!=null){
+            appendln(out,",");
+            pad(out, indent);
+            String pOperator = "\"physical-operator\":\"" + pOp.toString() + 
"\"";
+            append(out,pOperator);
+        }
+        appendln(out,",");
+        pad(out,indent);
+        append(out,"\"execution-mode\":\"" + op.getExecutionMode()+'"');
+        if (op.getInputs().size()>0) {
+            appendln(out,",");
+            pad(out,indent);
+            appendln(out, "\"inputs\":[");
+            boolean  moreInputes = false;
+            for (Mutable<ILogicalOperator> k : op.getInputs()) {
+                if (moreInputes) {
+                    append(out, ",");
+                }
+                printOperatorJson((AbstractLogicalOperator) k.getValue(), 
pvisitor, indent +4);
+                moreInputes = true;
+            }
+            pad(out, indent+2);
+            appendln(out, "]");
+        }
+        out.append("\n");
+        pad(out, indent-1);
+        appendln(out,"}");
+    }
     private static void printPhysicalOperator(AbstractLogicalOperator op, int 
indent, AlgebricksAppendable out)
             throws AlgebricksException {
         IPhysicalOperator pOp = op.getPhysicalOperator();
@@ -84,10 +135,25 @@
         buf.append(s);
         buf.append("\n");
     }
+    private static void append(AlgebricksAppendable buf, String s) throws 
AlgebricksException {
+        buf.append(s);
+    }
 
     private static void pad(AlgebricksAppendable buf, int indent) throws 
AlgebricksException {
         for (int i = 0; i < indent; ++i) {
             buf.append(' ');
         }
     }
+    public static void resetOperatorID(ILogicalPlan plan){
+        for (Mutable<ILogicalOperator> root : plan.getRoots()) {
+            AbstractLogicalOperator op = (AbstractLogicalOperator) 
root.getValue();
+            reset(op);
+        }
+    }
+    public static void reset(AbstractLogicalOperator op){
+        op.setOperatorID(0);
+        for (Mutable<ILogicalOperator> k : op.getInputs()) {
+            reset((AbstractLogicalOperator) k.getValue());
+        }
+    }
 }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
 
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
index c8b6e59..faa0937 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-examples/piglet-example/src/main/java/org/apache/hyracks/algebricks/examples/piglet/compiler/PigletCompiler.java
@@ -18,15 +18,6 @@
  */
 package org.apache.hyracks.algebricks.examples.piglet.compiler;
 
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;
 import 
org.apache.hyracks.algebricks.common.constraints.AlgebricksAbsolutePartitionConstraint;
@@ -41,39 +32,19 @@
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.ExpressionRuntimeProvider;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.*;
 import 
org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
 import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.*;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
-import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.LogicalOperatorPrettyPrintVisitor;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
 import org.apache.hyracks.algebricks.core.rewriter.base.AbstractRuleController;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 import org.apache.hyracks.algebricks.data.ISerializerDeserializerProvider;
 import org.apache.hyracks.algebricks.data.ITypeTraitProvider;
-import org.apache.hyracks.algebricks.examples.piglet.ast.ASTNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.AssignmentNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.DumpNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.ExpressionNode;
-import 
org.apache.hyracks.algebricks.examples.piglet.ast.FieldAccessExpressionNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.FilterNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.FunctionTag;
-import org.apache.hyracks.algebricks.examples.piglet.ast.LiteralExpressionNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.LoadNode;
-import org.apache.hyracks.algebricks.examples.piglet.ast.RelationNode;
-import 
org.apache.hyracks.algebricks.examples.piglet.ast.ScalarFunctionExpressionNode;
+import org.apache.hyracks.algebricks.examples.piglet.ast.*;
 import 
org.apache.hyracks.algebricks.examples.piglet.exceptions.PigletException;
 import 
org.apache.hyracks.algebricks.examples.piglet.metadata.PigletFileDataSink;
 import 
org.apache.hyracks.algebricks.examples.piglet.metadata.PigletFileDataSource;
@@ -88,6 +59,11 @@
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
 import org.apache.hyracks.api.job.JobSpecification;
 
+import java.io.Reader;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 public class PigletCompiler {
     private static final Logger LOGGER = 
Logger.getLogger(PigletCompiler.class.getName());
 

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/1885
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4dd62e355048a5b8a02e074049fe41e73e74e357
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: [email protected]

Reply via email to