[NO ISSUE][OTH] Make Query Service Parameters Extensible

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Make query service parameters extensible to allow
  extensions to set additional parameters.

Change-Id: Ice7b70279da899cce1fe89140bc158642fd13348
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3283
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index e0af3bd..df321bc 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -204,33 +204,37 @@
         this.multiStatement = multiStatement;
     }
 
+    public ObjectNode asJson() {
+        ObjectNode object = OBJECT_MAPPER.createObjectNode();
+        object.put("host", host);
+        object.put("path", path);
+        object.put("statement", statement != null ? JSONUtil.escape(new StringBuilder(), statement).toString() : null);
+        object.put("pretty", pretty);
+        object.put("mode", mode);
+        object.put("clientContextID", clientContextID);
+        object.put("format", format);
+        object.put("timeout", timeout);
+        object.put("maxResultReads", maxResultReads);
+        object.put("planFormat", planFormat);
+        object.put("expressionTree", expressionTree);
+        object.put("rewrittenExpressionTree", rewrittenExpressionTree);
+        object.put("logicalPlan", logicalPlan);
+        object.put("optimizedLogicalPlan", optimizedLogicalPlan);
+        object.put("job", job);
+        object.put("signature", signature);
+        object.put("multiStatement", multiStatement);
+        if (statementParams != null) {
+            for (Map.Entry<String, JsonNode> statementParam : statementParams.entrySet()) {
+                object.set('$' + statementParam.getKey(), statementParam.getValue());
+            }
+        }
+        return object;
+    }
+
     @Override
     public String toString() {
         try {
-            ObjectNode on = OBJECT_MAPPER.createObjectNode();
-            on.put("host", host);
-            on.put("path", path);
-            on.put("statement", statement != null ? JSONUtil.escape(new StringBuilder(), statement).toString() : null);
-            on.put("pretty", pretty);
-            on.put("mode", mode);
-            on.put("clientContextID", clientContextID);
-            on.put("format", format);
-            on.put("timeout", timeout);
-            on.put("maxResultReads", maxResultReads);
-            on.put("planFormat", planFormat);
-            on.put("expressionTree", expressionTree);
-            on.put("rewrittenExpressionTree", rewrittenExpressionTree);
-            on.put("logicalPlan", logicalPlan);
-            on.put("optimizedLogicalPlan", optimizedLogicalPlan);
-            on.put("job", job);
-            on.put("signature", signature);
-            on.put("multiStatement", multiStatement);
-            if (statementParams != null) {
-                for (Map.Entry<String, JsonNode> statementParam : statementParams.entrySet()) {
-                    on.set('$' + statementParam.getKey(), statementParam.getValue());
-                }
-            }
-            return OBJECT_MAPPER.writeValueAsString(on);
+            return OBJECT_MAPPER.writeValueAsString(asJson());
         } catch (JsonProcessingException e) {
             QueryServiceServlet.LOGGER.debug("unexpected exception marshalling {} instance to json", getClass(), e);
             return e.toString();
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 6e93c9e..1c66ce8 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
@@ -87,6 +87,7 @@
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonNode;
+
 import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class QueryServiceServlet extends AbstractQueryApiServlet {
@@ -449,10 +450,11 @@
         param.setStatementParams(
                 getOptStatementParameters(jsonRequest, jsonRequest.fieldNames(), JsonNode::get, v -> v));
         param.setMultiStatement(getOptBoolean(jsonRequest, Parameter.MULTI_STATEMENT, true));
-        setJsonOptionalParameters(jsonRequest, optionalParameters);
+        setJsonOptionalParameters(jsonRequest, param, optionalParameters);
     }
 
-    protected void setJsonOptionalParameters(JsonNode jsonRequest, Map<String, String> optionalParameters) {
+    protected void setJsonOptionalParameters(JsonNode jsonRequest, QueryServiceRequestParameters param,
+            Map<String, String> optionalParameters) {
         // allows extensions to set extra parameters
     }
 
@@ -474,10 +476,11 @@
         } catch (JsonParseException | JsonMappingException e) {
             GlobalConfig.ASTERIX_LOGGER.log(Level.ERROR, e.getMessage(), e);
         }
-        setOptionalParameters(request, optionalParameters);
+        setOptionalParameters(request, param, optionalParameters);
     }
 
-    protected void setOptionalParameters(IServletRequest request, Map<String, String> optionalParameters) {
+    protected void setOptionalParameters(IServletRequest request, QueryServiceRequestParameters param,
+            Map<String, String> optionalParameters) {
         // allows extensions to set extra parameters
     }
 
@@ -538,7 +541,7 @@
         Charset resultCharset = HttpUtil.setContentType(response, HttpUtil.ContentType.APPLICATION_JSON, request);
         PrintWriter httpWriter = response.writer();
         SessionOutput sessionOutput = createSessionOutput(httpWriter);
-        QueryServiceRequestParameters param = new QueryServiceRequestParameters();
+        QueryServiceRequestParameters param = newRequestParameters();
         try {
             // buffer the output until we are ready to set the status of the response message correctly
             sessionOutput.hold();
@@ -748,6 +751,10 @@
         pw.print(",\n");
     }
 
+    protected QueryServiceRequestParameters newRequestParameters() {
+        return new QueryServiceRequestParameters();
+    }
+
     private static boolean isJsonFormat(String format) {
         return format.startsWith(HttpUtil.ContentType.APPLICATION_JSON)
                 || format.equalsIgnoreCase(HttpUtil.ContentType.JSON);