Add Maven Plugin for Grammar Extension

This change introduces a new asterix maven plugin for grammar
extension. The plugin takes a base grammar file and an extension
file and combine them to generate an extended grammar. A base
grammar can be extended by overriding production nodes, adding
extending existing nodes, or introducing new terminals and
non terminals.

In addition, a mvn verify goal was added to generate the parser
java files from the grammar generated by the test.

Change-Id: Iaa2d11782d43dd8f27d69e347ed0fc8797d79dad
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1011
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
index 83e4375..9030da9 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AbstractLangTranslator.java
@@ -107,7 +107,7 @@
         String message = null;
         String dataverse = defaultDataverse != null ? defaultDataverse.getDataverseName() : null;
         switch (stmt.getKind()) {
-            case Statement.INSERT:
+            case Statement.Kind.INSERT:
                 InsertStatement insertStmt = (InsertStatement) stmt;
                 if (insertStmt.getDataverseName() != null) {
                     dataverse = insertStmt.getDataverseName().getValue();
@@ -119,7 +119,7 @@
                 }
                 break;
 
-            case Statement.DELETE:
+            case Statement.Kind.DELETE:
                 DeleteStatement deleteStmt = (DeleteStatement) stmt;
                 if (deleteStmt.getDataverseName() != null) {
                     dataverse = deleteStmt.getDataverseName().getValue();
@@ -131,7 +131,7 @@
                 }
                 break;
 
-            case Statement.NODEGROUP_DROP:
+            case Statement.Kind.NODEGROUP_DROP:
                 String nodegroupName = ((NodeGroupDropStatement) stmt).getNodeGroupName().getValue();
                 invalidOperation = MetadataConstants.METADATA_DEFAULT_NODEGROUP_NAME.equals(nodegroupName);
                 if (invalidOperation) {
@@ -139,7 +139,7 @@
                 }
                 break;
 
-            case Statement.DATAVERSE_DROP:
+            case Statement.Kind.DATAVERSE_DROP:
                 DataverseDropStatement dvDropStmt = (DataverseDropStatement) stmt;
                 invalidOperation =
                         MetadataConstants.METADATA_DATAVERSE_NAME.equals(dvDropStmt.getDataverseName().getValue());
@@ -148,7 +148,7 @@
                 }
                 break;
 
-            case Statement.DATASET_DROP:
+            case Statement.Kind.DATASET_DROP:
                 DropStatement dropStmt = (DropStatement) stmt;
                 if (dropStmt.getDataverseName() != null) {
                     dataverse = dropStmt.getDataverseName().getValue();
@@ -159,7 +159,7 @@
                             + MetadataConstants.METADATA_DATAVERSE_NAME;
                 }
                 break;
-            case Statement.DATASET_DECL:
+            case Statement.Kind.DATASET_DECL:
                 DatasetDecl datasetStmt = (DatasetDecl) stmt;
                 Map<String, String> hints = datasetStmt.getHints();
                 if (hints != null && !hints.isEmpty()) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
index 7a3b2a4..b184774 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/CompiledStatements.java
@@ -60,7 +60,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.DATASET_DROP;
+            return Statement.Kind.DATASET_DROP;
         }
     }
 
@@ -84,7 +84,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.CREATE_DATAVERSE;
+            return Statement.Kind.CREATE_DATAVERSE;
         }
     }
 
@@ -101,7 +101,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.NODEGROUP_DROP;
+            return Statement.Kind.NODEGROUP_DROP;
         }
     }
 
@@ -130,7 +130,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.INDEX_DROP;
+            return Statement.Kind.INDEX_DROP;
         }
     }
 
@@ -153,7 +153,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.DATAVERSE_DROP;
+            return Statement.Kind.DATAVERSE_DROP;
         }
     }
 
@@ -170,7 +170,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.TYPE_DROP;
+            return Statement.Kind.TYPE_DROP;
         }
     }
 
@@ -242,7 +242,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.CREATE_INDEX;
+            return Statement.Kind.CREATE_INDEX;
         }
     }
 
@@ -286,7 +286,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.LOAD;
+            return Statement.Kind.LOAD;
         }
     }
 
@@ -323,7 +323,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.INSERT;
+            return Statement.Kind.INSERT;
         }
     }
 
@@ -335,7 +335,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.UPSERT;
+            return Statement.Kind.UPSERT;
         }
     }
 
@@ -381,7 +381,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.CONNECT_FEED;
+            return Statement.Kind.CONNECT_FEED;
         }
 
         public String getPolicyName() {
@@ -419,7 +419,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.SUBSCRIBE_FEED;
+            return Statement.Kind.SUBSCRIBE_FEED;
         }
     }
 
@@ -450,7 +450,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.DISCONNECT_FEED;
+            return Statement.Kind.DISCONNECT_FEED;
         }
 
     }
@@ -495,7 +495,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.DELETE;
+            return Statement.Kind.DELETE;
         }
 
     }
@@ -519,7 +519,7 @@
 
         @Override
         public byte getKind() {
-            return Statement.COMPACT;
+            return Statement.Kind.COMPACT;
         }
     }
 
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 3689357..1894cc3 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -372,23 +372,23 @@
             Mutable<ILogicalExpression> varRef = new MutableObject<>(new VariableReferenceExpression(resVar));
             ILogicalOperator leafOperator;
             switch (stmt.getKind()) {
-                case Statement.INSERT:
+                case Statement.Kind.INSERT:
                     leafOperator = translateInsert(targetDatasource, varRef, varRefsForLoading,
                             additionalFilteringExpressions, assign);
                     break;
-                case Statement.UPSERT:
+                case Statement.Kind.UPSERT:
                     leafOperator = translateUpsert(targetDatasource, varRef, varRefsForLoading,
                             additionalFilteringExpressions, assign, additionalFilteringField);
                     break;
-                case Statement.DELETE:
+                case Statement.Kind.DELETE:
                     leafOperator = translateDelete(targetDatasource, varRef, varRefsForLoading,
                             additionalFilteringExpressions, assign);
                     break;
-                case Statement.CONNECT_FEED:
+                case Statement.Kind.CONNECT_FEED:
                     leafOperator = translateConnectFeed(targetDatasource, varRef, varRefsForLoading,
                             additionalFilteringExpressions, assign);
                     break;
-                case Statement.SUBSCRIBE_FEED:
+                case Statement.Kind.SUBSCRIBE_FEED:
                     leafOperator = translateSubscribeFeed((CompiledSubscribeFeedStatement) stmt, targetDatasource,
                             unnestVar, project, exprs, resVar, varRefsForLoading, varRef, assign,
                             additionalFilteringField, additionalFilteringAssign, additionalFilteringExpressions);
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 bef8a3a..af17c05 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
@@ -209,7 +209,7 @@
 
         ILogicalPlan plan;
         // statement = null when it's a query
-        if (statement == null || statement.getKind() != Statement.LOAD) {
+        if (statement == null || statement.getKind() != Statement.Kind.LOAD) {
             plan = t.translate(rwQ, outputDatasetName, statement);
         } else {
             plan = t.translateLoad(statement);
@@ -219,7 +219,7 @@
             conf.out().println();
 
             printPlanPrefix(conf, "Logical plan");
-            if (rwQ != null || (statement != null && statement.getKind() == Statement.LOAD)) {
+            if (rwQ != null || (statement != null && statement.getKind() == Statement.Kind.LOAD)) {
                 LogicalOperatorPrettyPrintVisitor pvisitor = new LogicalOperatorPrettyPrintVisitor(conf.out());
                 PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
             }
@@ -271,7 +271,7 @@
                     PlanPrettyPrinter.printPhysicalOps(plan, buffer, 0);
                 } else {
                     printPlanPrefix(conf, "Optimized logical plan");
-                    if (rwQ != null || (statement != null && statement.getKind() == Statement.LOAD)) {
+                    if (rwQ != null || (statement != null && statement.getKind() == Statement.Kind.LOAD)) {
                         LogicalOperatorPrettyPrintVisitor pvisitor = new LogicalOperatorPrettyPrintVisitor(conf.out());
                         PlanPrettyPrinter.printPlan(plan, pvisitor, 0);
                     }
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/AQLAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/AQLAPIServlet.java
index e799dd0..de19715 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/AQLAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/AQLAPIServlet.java
@@ -29,7 +29,7 @@
 
     private static final long serialVersionUID = 1L;
     private static final String AQL_STMT_PARAM_NAME = "aql";
-    private static final List<Byte> allowedStatements = Statement.VALUES;
+    private static final List<Byte> ALLOWED_STATEMENTS = Statement.KINDS;
 
     public AQLAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -42,7 +42,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        return allowedStatements;
+        return ALLOWED_STATEMENTS;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
index ec47276..0f9c537 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
@@ -28,6 +28,13 @@
 
 public class DDLAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
+    private static final List<Byte> STATEMENTS = Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL,
+            Statement.Kind.DATAVERSE_DROP, Statement.Kind.DATASET_DECL, Statement.Kind.NODEGROUP_DECL,
+            Statement.Kind.NODEGROUP_DROP, Statement.Kind.TYPE_DECL, Statement.Kind.TYPE_DROP,
+            Statement.Kind.CREATE_INDEX, Statement.Kind.INDEX_DECL, Statement.Kind.CREATE_DATAVERSE,
+            Statement.Kind.DATASET_DROP, Statement.Kind.INDEX_DROP, Statement.Kind.CREATE_FUNCTION,
+            Statement.Kind.FUNCTION_DROP, Statement.Kind.CREATE_PRIMARY_FEED, Statement.Kind.CREATE_SECONDARY_FEED,
+            Statement.Kind.DROP_FEED, Statement.Kind.CREATE_FEED_POLICY, Statement.Kind.DROP_FEED_POLICY });
 
     public DDLAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -40,13 +47,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        Byte[] statementsArray = { Statement.DATAVERSE_DECL, Statement.DATAVERSE_DROP, Statement.DATASET_DECL,
-                Statement.NODEGROUP_DECL, Statement.NODEGROUP_DROP, Statement.TYPE_DECL, Statement.TYPE_DROP,
-                Statement.CREATE_INDEX, Statement.INDEX_DECL, Statement.CREATE_DATAVERSE, Statement.DATASET_DROP,
-                Statement.INDEX_DROP, Statement.CREATE_FUNCTION, Statement.FUNCTION_DROP, Statement.CREATE_PRIMARY_FEED,
-                Statement.CREATE_SECONDARY_FEED, Statement.DROP_FEED, Statement.CREATE_FEED_POLICY,
-                Statement.DROP_FEED_POLICY };
-        return Arrays.asList(statementsArray);
+        return STATEMENTS;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
index 040ac1a..7262b59 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
@@ -28,6 +28,9 @@
 
 public class QueryAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
+    private static final List<Byte> STATEMENTS =
+            Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL, Statement.Kind.FUNCTION_DECL,
+                    Statement.Kind.QUERY, Statement.Kind.SET, Statement.Kind.WRITE, Statement.Kind.RUN });
 
     public QueryAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -40,9 +43,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        Byte[] statementsArray = { Statement.DATAVERSE_DECL, Statement.FUNCTION_DECL, Statement.QUERY, Statement.SET,
-                Statement.WRITE, Statement.RUN };
-        return Arrays.asList(statementsArray);
+        return STATEMENTS;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
index 9f762f8..22cd963 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
@@ -28,6 +28,11 @@
 
 public class UpdateAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
+    private static final List<Byte> STATEMENTS =
+            Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL, Statement.Kind.DELETE, Statement.Kind.INSERT,
+                    Statement.Kind.UPSERT, Statement.Kind.UPDATE, Statement.Kind.DML_CMD_LIST, Statement.Kind.LOAD,
+                    Statement.Kind.CONNECT_FEED, Statement.Kind.DISCONNECT_FEED, Statement.Kind.SET,
+                    Statement.Kind.COMPACT, Statement.Kind.EXTERNAL_DATASET_REFRESH, Statement.Kind.RUN });
 
     public UpdateAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -40,11 +45,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        Byte[] statementsArray =
-                { Statement.DATAVERSE_DECL, Statement.DELETE, Statement.INSERT, Statement.UPSERT, Statement.UPDATE,
-                        Statement.DML_CMD_LIST, Statement.LOAD, Statement.CONNECT_FEED, Statement.DISCONNECT_FEED,
-                        Statement.SET, Statement.COMPACT, Statement.EXTERNAL_DATASET_REFRESH, Statement.RUN };
-        return Arrays.asList(statementsArray);
+        return STATEMENTS;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/aql/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/aql/translator/QueryTranslator.java
index 4df4468..05d9b3d 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/aql/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/aql/translator/QueryTranslator.java
@@ -234,7 +234,7 @@
     private List<FunctionDecl> getDeclaredFunctions(List<Statement> statements) {
         List<FunctionDecl> functionDecls = new ArrayList<>();
         for (Statement st : statements) {
-            if (st.getKind() == Statement.FUNCTION_DECL) {
+            if (st.getKind() == Statement.Kind.FUNCTION_DECL) {
                 functionDecls.add((FunctionDecl) st);
             }
         }
@@ -284,98 +284,98 @@
                 metadataProvider.setOutputFile(outputFile);
                 metadataProvider.setConfig(config);
                 switch (stmt.getKind()) {
-                    case Statement.SET:
+                    case Statement.Kind.SET:
                         handleSetStatement(stmt, config);
                         break;
-                    case Statement.DATAVERSE_DECL:
+                    case Statement.Kind.DATAVERSE_DECL:
                         activeDefaultDataverse = handleUseDataverseStatement(metadataProvider, stmt);
                         break;
-                    case Statement.CREATE_DATAVERSE:
+                    case Statement.Kind.CREATE_DATAVERSE:
                         handleCreateDataverseStatement(metadataProvider, stmt);
                         break;
-                    case Statement.DATASET_DECL:
+                    case Statement.Kind.DATASET_DECL:
                         handleCreateDatasetStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.CREATE_INDEX:
+                    case Statement.Kind.CREATE_INDEX:
                         handleCreateIndexStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.TYPE_DECL:
+                    case Statement.Kind.TYPE_DECL:
                         handleCreateTypeStatement(metadataProvider, stmt);
                         break;
-                    case Statement.NODEGROUP_DECL:
+                    case Statement.Kind.NODEGROUP_DECL:
                         handleCreateNodeGroupStatement(metadataProvider, stmt);
                         break;
-                    case Statement.DATAVERSE_DROP:
+                    case Statement.Kind.DATAVERSE_DROP:
                         handleDataverseDropStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.DATASET_DROP:
+                    case Statement.Kind.DATASET_DROP:
                         handleDatasetDropStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.INDEX_DROP:
+                    case Statement.Kind.INDEX_DROP:
                         handleIndexDropStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.TYPE_DROP:
+                    case Statement.Kind.TYPE_DROP:
                         handleTypeDropStatement(metadataProvider, stmt);
                         break;
-                    case Statement.NODEGROUP_DROP:
+                    case Statement.Kind.NODEGROUP_DROP:
                         handleNodegroupDropStatement(metadataProvider, stmt);
                         break;
-                    case Statement.CREATE_FUNCTION:
+                    case Statement.Kind.CREATE_FUNCTION:
                         handleCreateFunctionStatement(metadataProvider, stmt);
                         break;
-                    case Statement.FUNCTION_DROP:
+                    case Statement.Kind.FUNCTION_DROP:
                         handleFunctionDropStatement(metadataProvider, stmt);
                         break;
-                    case Statement.LOAD:
+                    case Statement.Kind.LOAD:
                         handleLoadStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.INSERT:
-                    case Statement.UPSERT:
+                    case Statement.Kind.INSERT:
+                    case Statement.Kind.UPSERT:
                         handleInsertUpsertStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.DELETE:
+                    case Statement.Kind.DELETE:
                         handleDeleteStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.CREATE_PRIMARY_FEED:
-                    case Statement.CREATE_SECONDARY_FEED:
+                    case Statement.Kind.CREATE_PRIMARY_FEED:
+                    case Statement.Kind.CREATE_SECONDARY_FEED:
                         handleCreateFeedStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.DROP_FEED:
+                    case Statement.Kind.DROP_FEED:
                         handleDropFeedStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.DROP_FEED_POLICY:
+                    case Statement.Kind.DROP_FEED_POLICY:
                         handleDropFeedPolicyStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.CONNECT_FEED:
+                    case Statement.Kind.CONNECT_FEED:
                         handleConnectFeedStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.DISCONNECT_FEED:
+                    case Statement.Kind.DISCONNECT_FEED:
                         handleDisconnectFeedStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.SUBSCRIBE_FEED:
+                    case Statement.Kind.SUBSCRIBE_FEED:
                         handleSubscribeFeedStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.CREATE_FEED_POLICY:
+                    case Statement.Kind.CREATE_FEED_POLICY:
                         handleCreateFeedPolicyStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.QUERY:
+                    case Statement.Kind.QUERY:
                         metadataProvider.setResultSetId(new ResultSetId(resultSetIdCounter++));
                         metadataProvider.setResultAsyncMode(resultDelivery == ResultDelivery.ASYNC
                                 || resultDelivery == ResultDelivery.ASYNC_DEFERRED);
                         handleQuery(metadataProvider, (Query) stmt, hcc, hdc, resultDelivery, stats);
                         break;
-                    case Statement.COMPACT:
+                    case Statement.Kind.COMPACT:
                         handleCompactStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.EXTERNAL_DATASET_REFRESH:
+                    case Statement.Kind.EXTERNAL_DATASET_REFRESH:
                         handleExternalDatasetRefreshStatement(metadataProvider, stmt, hcc);
                         break;
-                    case Statement.WRITE:
+                    case Statement.Kind.WRITE:
                         Pair<IAWriterFactory, FileSplit> result = handleWriteStatement(stmt);
                         writerFactory = (result.first != null) ? result.first : writerFactory;
                         outputFile = result.second;
                         break;
-                    case Statement.RUN:
+                    case Statement.Kind.RUN:
                         handleRunStatement(metadataProvider, stmt, hcc);
                         break;
                     default:
@@ -1856,11 +1856,11 @@
             metadataProvider.setWriteTransaction(true);
             CompiledInsertStatement clfrqs = null;
             switch (stmtInsertUpsert.getKind()) {
-                case Statement.INSERT:
+                case Statement.Kind.INSERT:
                     clfrqs = new CompiledInsertStatement(dataverseName, stmtInsertUpsert.getDatasetName().getValue(),
                             query, stmtInsertUpsert.getVarCounter());
                     break;
-                case Statement.UPSERT:
+                case Statement.Kind.UPSERT:
                     clfrqs = new CompiledUpsertStatement(dataverseName, stmtInsertUpsert.getDatasetName().getValue(),
                             query, stmtInsertUpsert.getVarCounter());
                     break;
@@ -1963,13 +1963,13 @@
             }
 
             switch (stmt.getKind()) {
-                case Statement.CREATE_PRIMARY_FEED:
+                case Statement.Kind.CREATE_PRIMARY_FEED:
                     CreatePrimaryFeedStatement cpfs = (CreatePrimaryFeedStatement) stmt;
                     String adaptorName = cpfs.getAdaptorName();
                     feed = new Feed(dataverseName, feedName, cfs.getAppliedFunction(), FeedType.PRIMARY, feedName,
                             adaptorName, cpfs.getAdaptorConfiguration());
                     break;
-                case Statement.CREATE_SECONDARY_FEED:
+                case Statement.Kind.CREATE_SECONDARY_FEED:
                     CreateSecondaryFeedStatement csfs = (CreateSecondaryFeedStatement) stmt;
                     feed = new Feed(dataverseName, feedName, csfs.getAppliedFunction(), FeedType.SECONDARY,
                             csfs.getSourceFeedName(), null, null);
@@ -3102,4 +3102,4 @@
         rewriter.rewrite(stmt);
     }
 
-}
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
index 6bddfa5..05a7dce 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/sqlpp/ParserTestExecutor.java
@@ -128,7 +128,7 @@
             when(aqlMetadataProvider.findDataset(anyString(), anyString())).thenReturn(mock(Dataset.class));
 
             for (Statement st : statements) {
-                if (st.getKind() == Statement.QUERY) {
+                if (st.getKind() == Statement.Kind.QUERY) {
                     Query query = (Query) st;
                     IQueryRewriter rewriter = sqlppRewriterFactory.createQueryRewriter();
                     rewrite(rewriter, functions, query, aqlMetadataProvider,
@@ -156,7 +156,7 @@
     private List<FunctionDecl> getDeclaredFunctions(List<Statement> statements) {
         List<FunctionDecl> functionDecls = new ArrayList<FunctionDecl>();
         for (Statement st : statements) {
-            if (st.getKind() == Statement.FUNCTION_DECL) {
+            if (st.getKind() == Statement.Kind.FUNCTION_DECL) {
                 functionDecls.add((FunctionDecl) st);
             }
         }
@@ -166,7 +166,7 @@
     // Gets the default dataverse for the input statements.
     private String getDefaultDataverse(List<Statement> statements) {
         for (Statement st : statements) {
-            if (st.getKind() == Statement.DATAVERSE_DECL) {
+            if (st.getKind() == Statement.Kind.DATAVERSE_DECL) {
                 DataverseDecl dv = (DataverseDecl) st;
                 return dv.getDataverseName().getValue();
             }
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/FeedUtils.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/FeedUtils.java
index 6e1b9e8..9c378a0 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/FeedUtils.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/FeedUtils.java
@@ -64,7 +64,7 @@
         SPILL,              // Memory budget has been consumed. Now we're writing to disk
         DISCARD             // Memory and Disk space budgets have been consumed. Now we're discarding
     }
-    
+
     private FeedUtils() {
     }
 
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
index 14f229a..9e6f857 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/statement/SubscribeFeedStatement.java
@@ -52,7 +52,7 @@
  * Represents the AQL statement for subscribing to a feed.
  * This AQL statement is private and may not be used by the end-user.
  */
-public class SubscribeFeedStatement extends Statement {
+public class SubscribeFeedStatement implements Statement {
 
     private static final Logger LOGGER = Logger.getLogger(SubscribeFeedStatement.class.getName());
     private final FeedConnectionRequest connectionRequest;
@@ -158,7 +158,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.SUBSCRIBE_FEED;
+        return Statement.Kind.SUBSCRIBE_FEED;
     }
 
     public String getPolicy() {
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/RangeMapBuilder.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/RangeMapBuilder.java
index f30d4a6..2ee70bc 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/RangeMapBuilder.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/util/RangeMapBuilder.java
@@ -70,7 +70,7 @@
         }
 
         // Translate the query into a Range Map
-        if (hintStatements.get(0).getKind() != Statement.QUERY) {
+        if (hintStatements.get(0).getKind() != Statement.Kind.QUERY) {
             throw new AsterixException("Not a proper query for the range hint.");
         }
         Query q = (Query) hintStatements.get(0);
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index 586464c..7701278 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -504,12 +504,14 @@
   String datasetName = null;
 }
 {
+  (
     <REFRESH> <EXTERNAL> <DATASET> nameComponents = QualifiedName()
     {
     redss.setDataverseName(nameComponents.first);
     redss.setDatasetName(nameComponents.second);
     return redss;
     }
+  )
 }
 
 RunStatement RunStatement() throws ParseException:
@@ -1537,7 +1539,6 @@
       setDatasets(null);
       return query;
     }
-
 }
 
 
@@ -2201,7 +2202,7 @@
     }
 }
 
-Expression  FLWOGR() throws ParseException:
+Expression FLWOGR() throws ParseException:
 {
     FLWOGRExpression flworg = new FLWOGRExpression();
     List<Clause> clauseList = new ArrayList<Clause>();
@@ -2353,9 +2354,9 @@
 }
 Clause GroupClause()throws ParseException :
 {
-      GroupbyClause gbc = new GroupbyClause();
-      // GbyVariableExpressionPair pair = new GbyVariableExpressionPair();
-     List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
+    GroupbyClause gbc = new GroupbyClause();
+    // GbyVariableExpressionPair pair = new GbyVariableExpressionPair();
+    List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
     List<GbyVariableExpressionPair> decorPairList = new ArrayList<GbyVariableExpressionPair>();
     List<VariableExpr> withVarList= new ArrayList<VariableExpr>();
     VariableExpr var = null;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
index 6f0f1f1..fcc1080 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Statement.java
@@ -18,52 +18,75 @@
  */
 package org.apache.asterix.lang.common.base;
 
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-public abstract class Statement implements ILangExpression {
-    public static final byte DATASET_DECL = 0x00;
-    public static final byte DATAVERSE_DECL = 0x01;
-    public static final byte DATAVERSE_DROP = 0x02;
-    public static final byte DATASET_DROP = 0x03;
-    public static final byte DELETE = 0x04;
-    public static final byte INSERT = 0x05;
-    public static final byte UPSERT = 0x06;
-    public static final byte UPDATE = 0x07;
-    public static final byte DML_CMD_LIST = 0x08;
-    public static final byte FUNCTION_DECL = 0x09;
-    public static final byte LOAD = 0x0a;
-    public static final byte NODEGROUP_DECL = 0x0b;
-    public static final byte NODEGROUP_DROP = 0x0c;
-    public static final byte QUERY = 0x0d;
-    public static final byte SET = 0x0e;
-    public static final byte TYPE_DECL = 0x0f;
-    public static final byte TYPE_DROP = 0x10;
-    public static final byte WRITE = 0x11;
-    public static final byte CREATE_INDEX = 0x12;
-    public static final byte INDEX_DECL = 0x13;
-    public static final byte CREATE_DATAVERSE = 0x14;
-    public static final byte INDEX_DROP = 0x15;
-    public static final byte CREATE_PRIMARY_FEED = 0x16;
-    public static final byte CREATE_SECONDARY_FEED = 0x17;
-    public static final byte DROP_FEED = 0x18;
-    public static final byte CONNECT_FEED = 0x19;
-    public static final byte DISCONNECT_FEED = 0x1a;
-    public static final byte SUBSCRIBE_FEED = 0x1b;
-    public static final byte CREATE_FEED_POLICY = 0x1c;
-    public static final byte DROP_FEED_POLICY = 0x1d;
-    public static final byte CREATE_FUNCTION = 0x1e;
-    public static final byte FUNCTION_DROP = 0x1f;
-    public static final byte COMPACT = 0x20;
-    public static final byte EXTERNAL_DATASET_REFRESH = 0x21;
-    public static final byte RUN = 0x22;
-    public static final List<Byte> VALUES = Collections.unmodifiableList(
-            Arrays.asList(DATASET_DECL, DATAVERSE_DECL, DATAVERSE_DROP, DATASET_DROP, DELETE, INSERT, UPSERT, UPDATE,
-                    DML_CMD_LIST, FUNCTION_DECL, LOAD, NODEGROUP_DECL, NODEGROUP_DROP, QUERY, SET, TYPE_DECL, TYPE_DROP,
-                    WRITE, CREATE_INDEX, INDEX_DECL, CREATE_DATAVERSE, INDEX_DROP, CREATE_PRIMARY_FEED,
-                    CREATE_SECONDARY_FEED, DROP_FEED, CONNECT_FEED, DISCONNECT_FEED, SUBSCRIBE_FEED, CREATE_FEED_POLICY,
-                    DROP_FEED_POLICY, CREATE_FUNCTION, FUNCTION_DROP, COMPACT, EXTERNAL_DATASET_REFRESH, RUN));
+public interface Statement extends ILangExpression {
+    public static final List<Byte> KINDS = Collections.unmodifiableList(Kind.range(Kind.DATASET_DECL, Kind.RUN));
 
-    public abstract byte getKind();
+    /**
+     * get a byte representing the statement kind
+     * Note: bytes 0x00 - 0x7f are reserved for core asterix statements
+     * Use negative bytes for extension statements
+     *
+     * @return kind byte
+     */
+    public byte getKind();
+
+    public class Kind {
+        public static final byte DATASET_DECL = 0x00;
+        public static final byte DATAVERSE_DECL = 0x01;
+        public static final byte DATAVERSE_DROP = 0x02;
+        public static final byte DATASET_DROP = 0x03;
+        public static final byte DELETE = 0x04;
+        public static final byte INSERT = 0x05;
+        public static final byte UPSERT = 0x06;
+        public static final byte UPDATE = 0x07;
+        public static final byte DML_CMD_LIST = 0x08;
+        public static final byte FUNCTION_DECL = 0x09;
+        public static final byte LOAD = 0x0a;
+        public static final byte NODEGROUP_DECL = 0x0b;
+        public static final byte NODEGROUP_DROP = 0x0c;
+        public static final byte QUERY = 0x0d;
+        public static final byte SET = 0x0e;
+        public static final byte TYPE_DECL = 0x0f;
+        public static final byte TYPE_DROP = 0x10;
+        public static final byte WRITE = 0x11;
+        public static final byte CREATE_INDEX = 0x12;
+        public static final byte INDEX_DECL = 0x13;
+        public static final byte CREATE_DATAVERSE = 0x14;
+        public static final byte INDEX_DROP = 0x15;
+        public static final byte CREATE_PRIMARY_FEED = 0x16;
+        public static final byte CREATE_SECONDARY_FEED = 0x17;
+        public static final byte DROP_FEED = 0x18;
+        public static final byte CONNECT_FEED = 0x19;
+        public static final byte DISCONNECT_FEED = 0x1a;
+        public static final byte SUBSCRIBE_FEED = 0x1b;
+        public static final byte CREATE_FEED_POLICY = 0x1c;
+        public static final byte DROP_FEED_POLICY = 0x1d;
+        public static final byte CREATE_FUNCTION = 0x1e;
+        public static final byte FUNCTION_DROP = 0x1f;
+        public static final byte COMPACT = 0x20;
+        public static final byte EXTERNAL_DATASET_REFRESH = 0x21;
+        public static final byte RUN = 0x22;
+
+        private Kind() {
+        }
+
+        /**
+         * Generate a list of Bytes from start to end
+         *
+         * @param start
+         * @param end
+         * @return
+         */
+        private static List<Byte> range(byte start, byte end) {
+            ArrayList<Byte> bytes = new ArrayList<>();
+            for (byte b = start; b <= end; b++) {
+                bytes.add(b);
+            }
+            return bytes;
+        }
+    }
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CompactStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CompactStatement.java
index 531957f..912ac6f 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CompactStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CompactStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class CompactStatement extends Statement {
+public class CompactStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier datasetName;
@@ -35,7 +35,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.COMPACT;
+        return Statement.Kind.COMPACT;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ConnectFeedStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ConnectFeedStatement.java
index 33e3340..48bc59e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ConnectFeedStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/ConnectFeedStatement.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.metadata.feeds.BuiltinFeedPolicies;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
-public class ConnectFeedStatement extends Statement {
+public class ConnectFeedStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier datasetName;
@@ -78,7 +78,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CONNECT_FEED;
+        return Statement.Kind.CONNECT_FEED;
     }
 
     public String getPolicy() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateDataverseStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateDataverseStatement.java
index 7a5b722..c6dff3f 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateDataverseStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateDataverseStatement.java
@@ -24,7 +24,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.asterix.runtime.formats.NonTaggedDataFormat;
 
-public class CreateDataverseStatement extends Statement {
+public class CreateDataverseStatement implements Statement {
 
     private Identifier dataverseName;
     private String format;
@@ -50,7 +50,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_DATAVERSE;
+        return Statement.Kind.CREATE_DATAVERSE;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedPolicyStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedPolicyStatement.java
index e972cad..dfc6c7e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedPolicyStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedPolicyStatement.java
@@ -24,7 +24,7 @@
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class CreateFeedPolicyStatement extends Statement {
+public class CreateFeedPolicyStatement implements Statement {
 
     private final String policyName;
     private final String sourcePolicyName;
@@ -59,7 +59,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_FEED_POLICY;
+        return Statement.Kind.CREATE_FEED_POLICY;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedStatement.java
index 9635836..c4f9efb 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFeedStatement.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
-public abstract class CreateFeedStatement extends Statement {
+public abstract class CreateFeedStatement implements Statement {
 
     private final Pair<Identifier, Identifier> qName;
     private final FunctionSignature appliedFunction;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
index f7d0363..02a2b0c 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateFunctionStatement.java
@@ -27,7 +27,7 @@
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class CreateFunctionStatement extends Statement {
+public class CreateFunctionStatement implements Statement {
 
     private final FunctionSignature signature;
     private final String functionBody;
@@ -59,7 +59,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_FUNCTION;
+        return Statement.Kind.CREATE_FUNCTION;
     }
 
     public List<String> getParamList() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java
index a2337e1..fd787ab 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateIndexStatement.java
@@ -29,7 +29,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
-public class CreateIndexStatement extends Statement {
+public class CreateIndexStatement implements Statement {
 
     private Identifier indexName;
     private Identifier dataverseName;
@@ -120,7 +120,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_INDEX;
+        return Statement.Kind.CREATE_INDEX;
     }
 
     public boolean hasMetaField() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreatePrimaryFeedStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreatePrimaryFeedStatement.java
index 9dac0c4..6c4d84e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreatePrimaryFeedStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreatePrimaryFeedStatement.java
@@ -49,7 +49,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_PRIMARY_FEED;
+        return Statement.Kind.CREATE_PRIMARY_FEED;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateSecondaryFeedStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateSecondaryFeedStatement.java
index 7ef0a56..6787426 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateSecondaryFeedStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/CreateSecondaryFeedStatement.java
@@ -51,7 +51,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.CREATE_SECONDARY_FEED;
+        return Statement.Kind.CREATE_SECONDARY_FEED;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DatasetDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DatasetDecl.java
index fa88a9a..b2f3fe1 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DatasetDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DatasetDecl.java
@@ -27,7 +27,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class DatasetDecl extends Statement {
+public class DatasetDecl implements Statement {
     protected final Identifier name;
     protected final Identifier dataverse;
     protected final Identifier itemTypeDataverse;
@@ -142,7 +142,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DATASET_DECL;
+        return Statement.Kind.DATASET_DECL;
     }
 
     public IDatasetDetailsDecl getDatasetDetailsDecl() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDecl.java
index ae183e3..89933e5 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDecl.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class DataverseDecl extends Statement {
+public class DataverseDecl implements Statement {
 
     private Identifier dataverseName;
 
@@ -37,7 +37,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DATAVERSE_DECL;
+        return Statement.Kind.DATAVERSE_DECL;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDropStatement.java
index fe828fa..0054140 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DataverseDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class DataverseDropStatement extends Statement {
+public class DataverseDropStatement implements Statement {
 
     private Identifier dataverseName;
     private boolean ifExists;
@@ -35,7 +35,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DATAVERSE_DROP;
+        return Statement.Kind.DATAVERSE_DROP;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DeleteStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DeleteStatement.java
index c660d68..ffe2c0d 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DeleteStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DeleteStatement.java
@@ -28,7 +28,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.commons.lang3.ObjectUtils;
 
-public class DeleteStatement extends Statement {
+public class DeleteStatement implements Statement {
 
     private VariableExpr vars;
     private Identifier dataverseName;
@@ -52,7 +52,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DELETE;
+        return Statement.Kind.DELETE;
     }
 
     public VariableExpr getVariableExpr() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DisconnectFeedStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DisconnectFeedStatement.java
index 61ccc7a..9d8cb9d 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DisconnectFeedStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DisconnectFeedStatement.java
@@ -24,7 +24,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
-public class DisconnectFeedStatement extends Statement {
+public class DisconnectFeedStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier feedName;
@@ -62,7 +62,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DISCONNECT_FEED;
+        return Statement.Kind.DISCONNECT_FEED;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DropStatement.java
index f8becae..f4189dd 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/DropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class DropStatement extends Statement {
+public class DropStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier datasetName;
@@ -37,7 +37,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DATASET_DROP;
+        return Statement.Kind.DATASET_DROP;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedDropStatement.java
index 88f96ec..878fc49 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class FeedDropStatement extends Statement {
+public class FeedDropStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier feedName;
@@ -37,7 +37,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DROP_FEED;
+        return Statement.Kind.DROP_FEED;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedPolicyDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedPolicyDropStatement.java
index 73535fa..c217690 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedPolicyDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FeedPolicyDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class FeedPolicyDropStatement extends Statement {
+public class FeedPolicyDropStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier policyName;
@@ -37,7 +37,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.DROP_FEED_POLICY;
+        return Statement.Kind.DROP_FEED_POLICY;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
index 57a68f5..c71f7f2 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDecl.java
@@ -27,7 +27,7 @@
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class FunctionDecl extends Statement {
+public class FunctionDecl implements Statement {
     private FunctionSignature signature;
     private List<VarIdentifier> paramList;
     private Expression funcBody;
@@ -74,7 +74,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.FUNCTION_DECL;
+        return Statement.Kind.FUNCTION_DECL;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
index 9560180..ae1a29b 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/FunctionDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class FunctionDropStatement extends Statement {
+public class FunctionDropStatement implements Statement {
 
     private final FunctionSignature signature;
     private boolean ifExists;
@@ -35,7 +35,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.FUNCTION_DROP;
+        return Statement.Kind.FUNCTION_DROP;
     }
 
     public FunctionSignature getFunctionSignature() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDecl.java
index 06def0f..74cf0af 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDecl.java
@@ -23,6 +23,6 @@
 public class IndexDecl extends CreateIndexStatement {
     @Override
     public byte getKind() {
-        return Statement.INDEX_DECL;
+        return Statement.Kind.INDEX_DECL;
     }
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDropStatement.java
index e96a9d5..1e3f6b0 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/IndexDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class IndexDropStatement extends Statement {
+public class IndexDropStatement implements Statement {
 
     private Identifier dataverseName;
     private Identifier datasetName;
@@ -40,7 +40,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.INDEX_DROP;
+        return Statement.Kind.INDEX_DROP;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/InsertStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/InsertStatement.java
index 6d2c4f7..1e69a68 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/InsertStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/InsertStatement.java
@@ -24,7 +24,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.commons.lang3.ObjectUtils;
 
-public class InsertStatement extends Statement {
+public class InsertStatement implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier datasetName;
@@ -40,7 +40,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.INSERT;
+        return Statement.Kind.INSERT;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/LoadStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/LoadStatement.java
index efea76c..849b0bd 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/LoadStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/LoadStatement.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class LoadStatement extends Statement {
+public class LoadStatement implements Statement {
 
     private Identifier datasetName;
     private Identifier dataverseName;
@@ -68,7 +68,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.LOAD;
+        return Statement.Kind.LOAD;
     }
 
     public Identifier getDatasetName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodeGroupDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodeGroupDropStatement.java
index 5f6a0a2..710bedd 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodeGroupDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodeGroupDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class NodeGroupDropStatement extends Statement {
+public class NodeGroupDropStatement implements Statement {
 
     private Identifier nodeGroupName;
     private boolean ifExists;
@@ -35,7 +35,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.NODEGROUP_DROP;
+        return Statement.Kind.NODEGROUP_DROP;
     }
 
     public Identifier getNodeGroupName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodegroupDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodegroupDecl.java
index 25244ad..4232584 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodegroupDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/NodegroupDecl.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class NodegroupDecl extends Statement {
+public class NodegroupDecl implements Statement {
 
     private Identifier nodegroupName;
     private List<Identifier> nodeControllerNames;
@@ -55,7 +55,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.NODEGROUP_DECL;
+        return Statement.Kind.NODEGROUP_DECL;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
index 8a40ae9..80853c8 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
@@ -27,7 +27,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.commons.lang3.ObjectUtils;
 
-public class Query extends Statement {
+public class Query implements Statement {
     private boolean topLevel = true;
     private Expression body;
     private int varCounter;
@@ -72,7 +72,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.QUERY;
+        return Statement.Kind.QUERY;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RefreshExternalDatasetStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RefreshExternalDatasetStatement.java
index 47c4ca0..277b4bf 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RefreshExternalDatasetStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RefreshExternalDatasetStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class RefreshExternalDatasetStatement extends Statement {
+public class RefreshExternalDatasetStatement implements Statement {
 
     private Identifier dataverseName;
     private Identifier datasetName;
@@ -51,7 +51,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.EXTERNAL_DATASET_REFRESH;
+        return Statement.Kind.EXTERNAL_DATASET_REFRESH;
     }
 
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RunStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RunStatement.java
index bfdc4a0..6b33078 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RunStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/RunStatement.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class RunStatement extends Statement {
+public class RunStatement implements Statement {
 
     private String system;
     private List<String> parameters;
@@ -75,7 +75,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.RUN;
+        return Statement.Kind.RUN;
     }
 
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/SetStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/SetStatement.java
index 044e42a..54ba599 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/SetStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/SetStatement.java
@@ -22,7 +22,7 @@
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class SetStatement extends Statement {
+public class SetStatement implements Statement {
 
     private String propName;
     private String propValue;
@@ -42,7 +42,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.SET;
+        return Statement.Kind.SET;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDecl.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDecl.java
index 6d41640..e25688e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDecl.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDecl.java
@@ -25,7 +25,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class TypeDecl extends Statement {
+public class TypeDecl implements Statement {
 
     private final Identifier dataverseName;
     private final Identifier ident;
@@ -64,7 +64,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.TYPE_DECL;
+        return Statement.Kind.TYPE_DECL;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDropStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDropStatement.java
index a4bbe96..d675054 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDropStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/TypeDropStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class TypeDropStatement extends Statement {
+public class TypeDropStatement implements Statement {
 
     private final Identifier dataverseName;
     private Identifier typeName;
@@ -37,7 +37,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.TYPE_DROP;
+        return Statement.Kind.TYPE_DROP;
     }
 
     public Identifier getDataverseName() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpdateStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpdateStatement.java
index da74549..8ccc694 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpdateStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpdateStatement.java
@@ -28,7 +28,7 @@
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.commons.lang3.ObjectUtils;
 
-public class UpdateStatement extends Statement {
+public class UpdateStatement implements Statement {
 
     private VariableExpr vars;
     private Expression target;
@@ -44,7 +44,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.UPDATE;
+        return Statement.Kind.UPDATE;
     }
 
     public VariableExpr getVariableExpr() {
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpsertStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpsertStatement.java
index f562927..1fb1de2 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpsertStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/UpsertStatement.java
@@ -29,12 +29,12 @@
 
     @Override
     public byte getKind() {
-        return Statement.UPSERT;
+        return Statement.Kind.UPSERT;
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() + Statement.UPSERT;
+        return super.hashCode() + Statement.Kind.UPSERT;
     }
 
     @Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/WriteStatement.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/WriteStatement.java
index 1c49b9d..a755a54 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/WriteStatement.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/WriteStatement.java
@@ -23,7 +23,7 @@
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 
-public class WriteStatement extends Statement {
+public class WriteStatement implements Statement {
 
     private final Identifier ncName;
     private final String fileName;
@@ -49,7 +49,7 @@
 
     @Override
     public byte getKind() {
-        return Statement.WRITE;
+        return Statement.Kind.WRITE;
     }
 
     @Override
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/pom.xml b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/pom.xml
new file mode 100644
index 0000000..d3e4a41
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/pom.xml
@@ -0,0 +1,102 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.asterix</groupId>
+        <artifactId>asterix-maven-plugins</artifactId>
+        <version>0.8.9-SNAPSHOT</version>
+    </parent>
+    <artifactId>asterix-grammar-extension-maven-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>3.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <version>3.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-compat</artifactId>
+            <version>3.2.5</version>
+        </dependency>
+    <!-- dependencies to annotations -->
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>3.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.asterix</groupId>
+            <artifactId>asterix-external-data</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-testing</groupId>
+            <artifactId>maven-plugin-testing-harness</artifactId>
+            <version>3.3.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.asterix</groupId>
+            <artifactId>asterix-lang-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>javacc-maven-plugin</artifactId>
+                <version>2.6</version>
+                <executions>
+                    <execution>
+                        <id>javacc</id>
+                        <goals>
+                            <goal>javacc</goal>
+                        </goals>
+                        <phase>verify</phase>
+                        <configuration>
+                            <isStatic>false</isStatic>
+                            <javaUnicodeEscape>true</javaUnicodeEscape>
+                            <sourceDirectory>${project.build.directory}/generated-sources/lang</sourceDirectory>
+                            <outputDirectory>${project.build.directory}/generated-sources/javacc</outputDirectory>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>javacc-jjdoc</id>
+                        <goals>
+                            <goal>jjdoc</goal>
+                        </goals>
+                        <phase>verify</phase>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-plugin-plugin</artifactId>
+                    <version>3.3</version>
+                    <configuration>
+                        <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>mojo-descriptor</id>
+                            <phase>process-classes</phase>
+                            <goals>
+                                <goal>descriptor</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+</project>
\ No newline at end of file
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java
new file mode 100644
index 0000000..8f263f7
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/main/java/org/apache/asterix/extension/grammar/GrammarExtensionMojo.java
@@ -0,0 +1,841 @@
+/*
+ * 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.extension.grammar;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.asterix.external.input.record.CharArrayRecord;
+import org.apache.asterix.external.util.ExternalDataConstants;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * a Mojo for creating a grammar extension
+ */
+@Mojo(name = "grammarix")
+public class GrammarExtensionMojo extends AbstractMojo {
+
+    private static final String PARSER_BEGIN = "PARSER_BEGIN";
+    private static final String PARSER_END = "PARSER_END";
+    private static final char OPEN_BRACE = '{';
+    private static final char CLOSE_BRACE = '}';
+    private static final char OPEN_ANGULAR = '<';
+    private static final char CLOSE_ANGULAR = '>';
+    private static final char OPEN_PAREN = '(';
+    private static final char CLOSE_PAREN = ')';
+    private static final char SEMICOLON = ';';
+    private static final List<Character> SIG_SPECIAL_CHARS =
+            Arrays.asList(new Character[] { '(', ')', ':', '<', '>', ';', '.' });
+    private static final String KWCLASS = "class";
+    private static final String KWIMPORT = "import";
+    private static final String KWPACKAGE = "package";
+    private static final String NEWPRODUCTION = "@new";
+    private static final String MERGEPRODUCTION = "@merge";
+    private static final String OVERRIDEPRODUCTION = "@override";
+    private static final String BEFORE = "before:";
+    private static final String AFTER = "after:";
+    private static final List<String> KEYWORDS =
+            Arrays.asList(new String[] { KWCLASS, KWIMPORT, KWPACKAGE, PARSER_BEGIN, PARSER_END });
+    private static final List<String> EXTENSIONKEYWORDS =
+            Arrays.asList(new String[] { KWIMPORT, NEWPRODUCTION, OVERRIDEPRODUCTION, MERGEPRODUCTION });
+    private static final String REGEX_WS_DOT_SEMICOLON = "\\s|[.]|[;]";
+    private static final String REGEX_WS_PAREN = "\\s|[(]|[)]";
+    private static final String OPTIONS = "options";
+    private CharArrayRecord record = new CharArrayRecord();
+    private Position position = new Position();
+    private Map<String, Pair<String, String>> extensibles = new HashMap<>();
+    private Map<String, String[]> mergeElements = new HashMap<>();
+    private List<Pair<String, String>> finals = new ArrayList<>();
+    private List<List<String>> imports = new ArrayList<>();
+    private String baseClassName;
+    private String baseClassDef;
+    private String optionsBlock;
+    private boolean read = false;
+
+    @Parameter(property = "grammarix.base")
+    private String base;
+
+    @Parameter(property = "grammarix.extension")
+    private String extension;
+
+    @Parameter(property = "grammarix.output")
+    private String output;
+
+    @Parameter(property = "grammarix.packageName")
+    private String packageName;
+
+    @Parameter(property = "grammarix.parserClassName")
+    private String parserClassName;
+    private String lastIdentifier;
+
+    @Override
+    public void execute() throws MojoExecutionException {
+        getLog().info("Current dir: " + System.getProperty("user.dir"));
+        getLog().info("base: " + base);
+        getLog().info("extension: " + extension);
+        processBase();
+        processExtension();
+        generateOutput();
+    }
+
+    private void generateOutput() throws MojoExecutionException {
+        File outputFile = prepareOutputFile();
+        try (BufferedWriter writer = Files.newBufferedWriter(outputFile.toPath(), StandardCharsets.UTF_8)) {
+            // Options
+            if (optionsBlock != null) {
+                writer.write(OPTIONS);
+                writer.write(optionsBlock);
+            }
+            writer.newLine();
+
+            // Parser Begin
+            writer.write(PARSER_BEGIN);
+            writer.write(OPEN_PAREN);
+            writer.write(parserClassName);
+            writer.write(CLOSE_PAREN);
+            writer.newLine();
+            writer.newLine();
+
+            // Package
+            writer.write(KWPACKAGE);
+            writer.write(" ");
+            writer.write(packageName);
+            writer.write(SEMICOLON);
+            writer.newLine();
+            writer.newLine();
+
+            // Imports
+            List<String> importList = new ArrayList<>();
+            for (List<String> importTokens : imports) {
+                importList.add(importToString(importTokens));
+            }
+            Collections.sort(importList);
+            for (String importStatement : importList) {
+                writer.write(importStatement);
+                writer.newLine();
+            }
+
+            writer.newLine();
+
+            // Class definition
+            writer.write(baseClassDef.replaceAll(baseClassName, parserClassName));
+            writer.newLine();
+
+            // Parser End
+            writer.write(PARSER_END);
+            writer.write(OPEN_PAREN);
+            writer.write(parserClassName);
+            writer.write(CLOSE_PAREN);
+            writer.newLine();
+            writer.newLine();
+
+            // Extinsibles
+            for (Entry<String, Pair<String, String>> entry : extensibles.entrySet()) {
+                writer.newLine();
+                String signature = entry.getKey();
+                if (mergeElements.containsKey(signature)) {
+                    writer.write("// Merged Non-terminal");
+                    writer.newLine();
+                }
+                writer.write(extensibleSignatureToOutput(signature));
+                writer.newLine();
+                if (mergeElements.containsKey(signature)) {
+                    merge(writer, entry.getValue(), mergeElements.get(signature));
+                } else {
+                    writer.write(entry.getValue().first);
+                    writer.newLine();
+                    if (entry.getValue().second != null) {
+                        writer.write(entry.getValue().second);
+                        writer.newLine();
+                    }
+                }
+            }
+
+            for (Pair<String, String> element : finals) {
+                writer.write(toOutput(element.first));
+                writer.newLine();
+                writer.write(element.second);
+                writer.newLine();
+            }
+
+        } catch (Exception e) {
+            getLog().error(e);
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private String extensibleSignatureToOutput(String signature) {
+        StringBuilder aString = new StringBuilder();
+        String[] tokens = signature.split(" ");
+        aString.append(tokens[0]);
+        for (int i = 1; i < tokens.length; i++) {
+            if (tokens[i - 1].charAt(tokens[i - 1].length() - 1) == CLOSE_PAREN
+                    || (!SIG_SPECIAL_CHARS.contains(tokens[i].charAt(0))
+                            && !SIG_SPECIAL_CHARS.contains(tokens[i - 1].charAt(tokens[i - 1].length() - 1)))) {
+                aString.append(" ");
+            }
+            aString.append(tokens[i]);
+        }
+        return aString.toString();
+    }
+
+    private String toOutput(String signature) {
+        if (signature.indexOf(OPEN_ANGULAR) == 0) {
+            // a final
+            StringBuilder aString = new StringBuilder();
+            aString.append(signature.substring(0, signature.indexOf(CLOSE_ANGULAR) + 1));
+            aString.append('\n');
+            aString.append(signature.substring(signature.indexOf(CLOSE_ANGULAR) + 1));
+            return aString.toString();
+        } else {
+            return signature;
+        }
+    }
+
+    private void merge(BufferedWriter writer, Pair<String, String> baseBlocks, String[] extensions)
+            throws IOException, MojoExecutionException {
+        String errorMessage = "Merged base node doesn't conform to expected mergable node structure";
+        int block1Open = baseBlocks.first.indexOf(OPEN_BRACE);
+        int block1Close = baseBlocks.first.lastIndexOf(CLOSE_BRACE);
+        // first block
+        writer.write(OPEN_BRACE);
+        if (extensions[0] != null) {
+            writer.write(extensions[0]);
+        }
+        writer.write(baseBlocks.first.substring(block1Open + 1, block1Close));
+        if (extensions[1] != null) {
+            writer.write(extensions[1]);
+        }
+        writer.write(CLOSE_BRACE);
+        writer.newLine();
+        // second block
+        writer.write(OPEN_BRACE);
+        writer.newLine();
+        writer.write("  ");
+        writer.write(OPEN_PAREN);
+        if (extensions[2] != null) {
+            writer.write(extensions[2]);
+        }
+        String innerBlock2String = null;
+        if (baseBlocks.second != null) {
+            BufferedReader blockReader = stringToReader(baseBlocks.second);
+            Position blockPosition = new Position();
+            blockPosition.index = 0;
+            blockPosition.line = blockReader.readLine();
+            while (blockPosition.line != null && blockPosition.line.trim().length() == 0) {
+                blockPosition.line = blockReader.readLine();
+            }
+            int block2Open = blockPosition.line.indexOf(OPEN_BRACE);
+            if (block2Open < 0) {
+                throw new MojoExecutionException(errorMessage);
+            }
+            blockPosition.line = blockPosition.line.substring(block2Open + 1);
+            while (blockPosition.line != null && blockPosition.line.trim().length() == 0) {
+                blockPosition.line = blockReader.readLine();
+            }
+            int innerBlock1Open = blockPosition.line.indexOf(OPEN_PAREN);
+            if (innerBlock1Open < 0) {
+                throw new MojoExecutionException(errorMessage);
+            }
+            blockPosition.index = innerBlock1Open;
+            readBlock(blockReader, OPEN_PAREN, CLOSE_PAREN, blockPosition);
+            String innerBlock1String = record.toString();
+            writer.newLine();
+            writer.write("    ");
+            writer.write(innerBlock1String
+                    .substring(innerBlock1String.indexOf(OPEN_PAREN) + 1, innerBlock1String.lastIndexOf(CLOSE_PAREN))
+                    .trim());
+            writer.newLine();
+            record.reset();
+            // read second inner block
+            blockPosition.line = blockReader.readLine();
+            while (blockPosition.line != null && blockPosition.line.trim().length() == 0) {
+                blockPosition.line = blockReader.readLine();
+            }
+            int innerBlock2Open = blockPosition.line.indexOf(OPEN_BRACE);
+            if (innerBlock2Open < 0) {
+                throw new MojoExecutionException(errorMessage);
+            }
+            blockPosition.index = innerBlock2Open;
+            readBlock(blockReader, OPEN_BRACE, CLOSE_BRACE, blockPosition);
+            innerBlock2String = record.toString();
+            record.reset();
+        }
+        if (extensions[3] != null) {
+            writer.write(extensions[3]);
+        }
+        writer.newLine();
+        writer.write("  ");
+        writer.write(CLOSE_PAREN);
+        writer.newLine();
+        writer.write("  ");
+        writer.write(OPEN_BRACE);
+        if (extensions[4] != null) {
+            writer.write(extensions[4]);
+        }
+        if (innerBlock2String != null) {
+            writer.newLine();
+            writer.write("  ");
+            writer.write(innerBlock2String
+                    .substring(innerBlock2String.indexOf(OPEN_BRACE) + 1, innerBlock2String.lastIndexOf(CLOSE_BRACE))
+                    .trim());
+            writer.newLine();
+        }
+        if (extensions[5] != null) {
+            writer.write(extensions[5]);
+        }
+        // Close inner second block
+        writer.write("  ");
+        writer.write(CLOSE_BRACE);
+        writer.newLine();
+        // Close second block
+        writer.write(CLOSE_BRACE);
+        writer.newLine();
+    }
+
+    class Position {
+        String line;
+        int index;
+    }
+
+    private void readBlock(BufferedReader reader, char start, char end) throws IOException, MojoExecutionException {
+        readBlock(reader, start, end, position);
+    }
+
+    private void readBlock(BufferedReader reader, char start, char end, Position position)
+            throws IOException, MojoExecutionException {
+        record.reset();
+        char[] chars = position.line.toCharArray();
+        if (chars[position.index] != start) {
+            throw new MojoExecutionException(
+                    "attempt to read a non terminal that doesn't start with a brace. @Line: " + position.line);
+        }
+        boolean prevCharEscape = false;
+        boolean inString = false;
+        boolean hasFinished = false;
+        int depth = 0;
+        int bufferPosn = position.index;
+        int bufferLength = chars.length;
+        do {
+            int startPosn = bufferPosn;
+            if (bufferPosn >= bufferLength) {
+                startPosn = bufferPosn = 0;
+                record.append("\n".toCharArray());
+                position.line = reader.readLine();
+                chars = position.line.toCharArray();
+                bufferLength = chars.length;
+            }
+            for (; bufferPosn < bufferLength; ++bufferPosn) {
+                if (inString) {
+                    // we are in a string, we only care about the string end
+                    if (chars[bufferPosn] == ExternalDataConstants.QUOTE && !prevCharEscape) {
+                        inString = false;
+                    }
+                    if (prevCharEscape) {
+                        prevCharEscape = false;
+                    } else {
+                        prevCharEscape = chars[bufferPosn] == ExternalDataConstants.ESCAPE;
+                    }
+                } else {
+                    if (chars[bufferPosn] == ExternalDataConstants.QUOTE) {
+                        inString = true;
+                    } else if (chars[bufferPosn] == start) {
+                        depth += 1;
+                    } else if (chars[bufferPosn] == end) {
+                        depth -= 1;
+                        if (depth == 0) {
+                            hasFinished = true;
+                            bufferPosn++;
+                            position.index = bufferPosn;
+                            break;
+                        }
+                    }
+                }
+            }
+            int appendLength = bufferPosn - startPosn;
+            if (appendLength > 0) {
+                record.append(chars, startPosn, appendLength);
+            }
+        } while (!hasFinished);
+        record.endRecord();
+    }
+
+    private void processBase() throws MojoExecutionException {
+        try (BufferedReader reader = Files.newBufferedReader(Paths.get(base), StandardCharsets.UTF_8)) {
+            StringBuilder identifier = new StringBuilder();
+            while ((position.line = reader.readLine()) != null) {
+                if (position.line.trim().startsWith("//")) {
+                    // skip comments
+                    continue;
+                }
+                String[] tokens = position.line.split(REGEX_WS_PAREN);
+                position.index = 0;
+                int openBraceIndex = position.line.indexOf(OPEN_BRACE);
+                int openAngularIndex = position.line.trim().indexOf(OPEN_ANGULAR);
+                if (tokens.length > 0 && identifier.length() == 0 && KEYWORDS.contains(tokens[0])) {
+                    handleSpecialToken(tokens[0], reader);
+                } else if (openBraceIndex >= 0 && openAngularIndex < 0) {
+                    String beforeBrace = position.line.substring(0, openBraceIndex);
+                    if (beforeBrace.trim().length() > 0) {
+                        identifier.append(beforeBrace);
+                    } else if (identifier.length() == 0) {
+                        identifier.append(lastIdentifier);
+                    }
+                    position.index = openBraceIndex;
+                    readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+                    // if next non-white space character is an open brace, then  we need to append
+                    addExtensibleProduction(identifier);
+                } else if (openAngularIndex == 0) {
+                    position.index = position.line.indexOf(OPEN_ANGULAR);
+                    readFinalProduction(identifier, reader);
+                    addFinalProduction(identifier);
+                } else if (identifier.length() > 0 || position.line.trim().length() > 0) {
+                    identifier.append(position.line);
+                    identifier.append('\n');
+                }
+            }
+        } catch (Exception e) {
+            getLog().error(e);
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private void handleSpecialToken(String token, BufferedReader reader) throws IOException, MojoExecutionException {
+        switch (token) {
+            case PARSER_BEGIN:
+                // parser begin. duh!
+                parserBegin(reader);
+                break;
+            case PARSER_END:
+                // parser end
+                parserEnd(reader);
+                break;
+            case KWCLASS:
+                // class declaration
+                handleClassDeclaration(reader);
+                break;
+            case KWPACKAGE:
+                // package declaration
+                skipPackageDeclaration(reader);
+                break;
+            case KWIMPORT:
+                handleImport(reader);
+                // import statement
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void addFinalProduction(StringBuilder identifier) {
+        String sig = toSignature(identifier.toString());
+        finals.add(new Pair<String, String>(sig, record.toString()));
+        record.reset();
+        identifier.setLength(0);
+        lastIdentifier = null;
+    }
+
+    private void handleImport(BufferedReader reader) throws IOException {
+        // will not work on two imports on a single line
+        ArrayList<String> importList = new ArrayList<>();
+        String[] tokens = position.line.split(REGEX_WS_DOT_SEMICOLON);
+        importList.addAll(Arrays.asList(tokens));
+        while (position.line.indexOf(SEMICOLON) < 0) {
+            position.line = reader.readLine();
+            tokens = position.line.split(REGEX_WS_DOT_SEMICOLON);
+            importList.addAll(Arrays.asList(tokens));
+        }
+        imports.add(importList);
+    }
+
+    private String importToString(List<String> importTokens) {
+        return "import " + StringUtils.join(importTokens.subList(1, importTokens.size()), '.') + ";";
+    }
+
+    private void skipPackageDeclaration(BufferedReader reader) throws IOException {
+        while (position.line.indexOf(SEMICOLON) < 0) {
+            position.line = reader.readLine();
+        }
+    }
+
+    private void handleClassDeclaration(BufferedReader reader) throws IOException, MojoExecutionException {
+        StringBuilder parserDef = new StringBuilder();
+        int classPosition = position.line.indexOf(KWCLASS);
+        int startIndex = position.line.indexOf(OPEN_BRACE, classPosition);
+        if (startIndex < 0) {
+            position.line = position.line.substring(classPosition).replace(baseClassName, parserClassName);
+            while (startIndex < 0) {
+                parserDef.append(position.line);
+                parserDef.append('\n');
+                position.line = reader.readLine();
+                startIndex = position.line.indexOf(OPEN_BRACE);
+            }
+            parserDef.append(position.line, 0, startIndex);
+        } else {
+            parserDef.append(position.line, classPosition, startIndex);
+        }
+        position.index = startIndex;
+        readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+        String classBody = record.toString();
+        parserDef.append(classBody);
+        parserDef.append('\n');
+        baseClassDef = parserDef.toString();
+    }
+
+    private void parserEnd(BufferedReader reader) throws IOException {
+        int endIndex = position.line.indexOf(CLOSE_PAREN, position.index);
+        while (endIndex < 0) {
+            position.line = reader.readLine();
+            endIndex = position.line.indexOf(CLOSE_PAREN);
+        }
+        position.index = endIndex;
+    }
+
+    private void parserBegin(BufferedReader reader) throws IOException {
+        StringBuilder aStringBuilder = new StringBuilder();
+        int startIndex = position.line.indexOf(OPEN_PAREN, position.index);
+        while (startIndex < 0) {
+            position.line = reader.readLine();
+            startIndex = position.line.indexOf(OPEN_PAREN);
+        }
+        int endIndex = position.line.indexOf(CLOSE_PAREN, startIndex);
+        if (endIndex < 0) {
+            // start and end on different lines
+            position.line = position.line.substring(startIndex + 1);
+            while (endIndex < 0) {
+                aStringBuilder.append(position.line);
+                position.line = reader.readLine();
+                endIndex = position.line.indexOf(CLOSE_PAREN);
+            }
+            aStringBuilder.append(position.line, 0, endIndex);
+        } else {
+            // start and end on the same line
+            aStringBuilder.append(position.line.substring(startIndex + 1, endIndex));
+        }
+        position.index = endIndex;
+        baseClassName = aStringBuilder.toString().trim();
+    }
+
+    private void readFinalProduction(StringBuilder identifier, BufferedReader reader)
+            throws IOException, MojoExecutionException {
+        int blockStart = position.line.indexOf(OPEN_BRACE);
+        if (blockStart < 0) {
+            position.line = position.line.substring(position.index);
+            while (blockStart < 0) {
+                identifier.append(position.line);
+                identifier.append('\n');
+                position.line = reader.readLine();
+                blockStart = position.line.indexOf(OPEN_BRACE);
+            }
+            identifier.append(position.line.substring(0, blockStart));
+        } else {
+            identifier.append(position.line.substring(position.index, blockStart));
+        }
+        position.index = blockStart;
+        readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+    }
+
+    private void addExtensibleProduction(StringBuilder identifier) {
+        if (identifier.toString().trim().equals(OPTIONS)) {
+            optionsBlock = record.toString();
+        } else {
+            String sig = toSignature(identifier.toString());
+            Pair<String, String> pair = extensibles.get(sig);
+            if (pair == null) {
+                pair = new Pair<>(record.toString(), null);
+                extensibles.put(sig, pair);
+            } else {
+                pair.second = record.toString();
+            }
+            lastIdentifier = identifier.toString();
+        }
+        record.reset();
+        identifier.setLength(0);
+    }
+
+    private void processExtension() throws MojoExecutionException {
+        try (BufferedReader reader = Files.newBufferedReader(Paths.get(extension), StandardCharsets.UTF_8)) {
+            StringBuilder identifier = new StringBuilder();
+            String nextOperation = OVERRIDEPRODUCTION;
+            while (read || (position.line = reader.readLine()) != null) {
+                read = false;
+                if (position.line.trim().startsWith("//")) {
+                    // skip comments
+                    continue;
+                }
+                String[] tokens = position.line.split(REGEX_WS_PAREN);
+                position.index = 0;
+                int openBraceIndex = position.line.indexOf(OPEN_BRACE);
+                int openAngularIndex = position.line.trim().indexOf(OPEN_ANGULAR);
+                if (tokens.length > 0 && identifier.length() == 0 && EXTENSIONKEYWORDS.contains(tokens[0])) {
+                    switch (tokens[0]) {
+                        case KWIMPORT:
+                            handleImport(reader);
+                            // import statement
+                            break;
+                        case NEWPRODUCTION:
+                            nextOperation = NEWPRODUCTION;
+                            break;
+                        case MERGEPRODUCTION:
+                            nextOperation = MERGEPRODUCTION;
+                            break;
+                        case OVERRIDEPRODUCTION:
+                            nextOperation = OVERRIDEPRODUCTION;
+                            break;
+                        default:
+                            break;
+                    }
+                } else if (openBraceIndex >= 0 && openAngularIndex < 0) {
+                    String beforeBrace = position.line.substring(0, openBraceIndex);
+                    if (beforeBrace.trim().length() > 0) {
+                        identifier.append(beforeBrace);
+                    } else if (identifier.length() == 0) {
+                        identifier.append(lastIdentifier);
+                    }
+                    position.index = openBraceIndex;
+                    switch (nextOperation) {
+                        case NEWPRODUCTION:
+                            handleNew(identifier, reader);
+                            break;
+                        case OVERRIDEPRODUCTION:
+                            handleOverride(identifier, reader);
+                            break;
+                        case MERGEPRODUCTION:
+                            handleMerge(identifier, reader);
+                            break;
+                        default:
+                            throw new MojoExecutionException("Malformed extention file");
+                    }
+                    nextOperation = NEWPRODUCTION;
+                } else if (openAngularIndex == 0) {
+                    if (nextOperation != NEWPRODUCTION) {
+                        throw new MojoExecutionException("Can only add new REGEX production kind");
+                    }
+                    position.index = position.line.indexOf(OPEN_ANGULAR);
+                    readFinalProduction(identifier, reader);
+                    addFinalProduction(identifier);
+                } else if (identifier.length() > 0 || position.line.trim().length() > 0) {
+                    identifier.append(position.line);
+                    identifier.append('\n');
+                }
+            }
+        } catch (Exception e) {
+            getLog().error(e);
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private void handleOverride(StringBuilder identifier, BufferedReader reader)
+            throws MojoExecutionException, IOException {
+        readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+        Pair<String, String> pair = new Pair<>(record.toString(), null);
+        String sig = toSignature(identifier.toString());
+        extensibles.put(sig, pair);
+        record.reset();
+        identifier.setLength(0);
+        // will read ahead of loop cycle
+        read = true;
+        position.index = 0;
+        position.line = reader.readLine();
+        while (position.line != null && position.line.trim().length() == 0) {
+            position.line = reader.readLine();
+        }
+        int openBraceIndex = position.line.indexOf(OPEN_BRACE);
+        if (openBraceIndex > -1) {
+            // consume
+            read = false;
+            position.index = openBraceIndex;
+            readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+            pair.second = record.toString();
+            record.reset();
+        }
+    }
+
+    private void handleNew(StringBuilder identifier, BufferedReader reader) throws MojoExecutionException, IOException {
+        String sig = toSignature(identifier.toString());
+        if (extensibles.containsKey(sig)) {
+            throw new MojoExecutionException(identifier.toString() + " already exists in base grammar");
+        }
+        handleOverride(identifier, reader);
+    }
+
+    private void handleMerge(StringBuilder identifier, BufferedReader reader)
+            throws MojoExecutionException, IOException {
+        String sig = toSignature(identifier.toString());
+        if (!extensibles.containsKey(sig)) {
+            throw new MojoExecutionException(identifier.toString() + " doesn't exist in base grammar");
+        }
+        String[] amendments = new String[6];
+        mergeElements.put(sig, amendments);
+        // we don't need the identifier anymore
+        identifier.setLength(0);
+        readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+        String block = record.toString();
+        extractBeforeAndAfter(block, amendments, 0, 1);
+        record.reset();
+        position.index = 0;
+        position.line = reader.readLine();
+        while (position.line != null && position.line.trim().length() == 0) {
+            position.line = reader.readLine();
+        }
+        int openBraceIndex = position.line.indexOf(OPEN_BRACE);
+        if (openBraceIndex > -1) {
+            position.index = openBraceIndex;
+            readBlock(reader, OPEN_BRACE, CLOSE_BRACE);
+        } else {
+            throw new MojoExecutionException("merge element doesn't have a second block");
+        }
+        block = record.toString();
+        BufferedReader blockReader = stringToReader(block);
+        String line = blockReader.readLine();
+        while (line != null && line.indexOf(OPEN_BRACE) < 0) {
+            line = blockReader.readLine();
+        }
+        if (line == null) {
+            throw new MojoExecutionException("merge element doesn't have a correct second block");
+        }
+        line = line.substring(line.indexOf(OPEN_BRACE) + 1);
+        while (line != null && line.trim().length() == 0) {
+            line = blockReader.readLine();
+        }
+        if (line == null) {
+            throw new MojoExecutionException("merge element doesn't have a correct second block");
+        }
+        int openParenIndex = line.indexOf(OPEN_PAREN);
+        if (openParenIndex < 0) {
+            throw new MojoExecutionException("second block in merge element doesn't have a correct () block");
+        }
+        Position blockPosition = new Position();
+        blockPosition.line = line;
+        blockPosition.index = openParenIndex;
+        readBlock(blockReader, OPEN_PAREN, CLOSE_PAREN, blockPosition);
+        extractBeforeAndAfter(record.toString(), amendments, 2, 3);
+        record.reset();
+        // process third block:
+        blockPosition.index = 0;
+        blockPosition.line = blockReader.readLine();
+        while (blockPosition.line != null && blockPosition.line.trim().length() == 0) {
+            blockPosition.line = blockReader.readLine();
+        }
+        openBraceIndex = blockPosition.line.indexOf(OPEN_BRACE);
+        if (openBraceIndex > -1) {
+            blockPosition.index = openBraceIndex;
+            readBlock(blockReader, OPEN_BRACE, CLOSE_BRACE, blockPosition);
+        } else {
+            throw new MojoExecutionException("merge element doesn't have a second block");
+        }
+        extractBeforeAndAfter(record.toString(), amendments, 4, 5);
+        record.reset();
+    }
+
+    private void extractBeforeAndAfter(String block, String[] amendments, int beforeIndex, int afterIndex) {
+        int before = block.indexOf(BEFORE);
+        int after = block.indexOf(AFTER);
+        if (before >= 0) {
+            // before exists
+            amendments[beforeIndex] =
+                    block.substring(before + BEFORE.length(), (after >= 0) ? after : block.length() - 1);
+            if (amendments[beforeIndex].trim().length() == 0) {
+                amendments[beforeIndex] = null;
+            }
+        }
+        if (after >= 0) {
+            // after exists
+            amendments[afterIndex] = block.substring(after + AFTER.length(), block.length() - 1);
+            if (amendments[afterIndex].trim().length() == 0) {
+                amendments[afterIndex] = null;
+            }
+        }
+    }
+
+    private BufferedReader stringToReader(String aString) {
+        InputStream is = new ByteArrayInputStream(aString.getBytes(StandardCharsets.UTF_8));
+        return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+    }
+
+    private File prepareOutputFile() throws MojoExecutionException {
+        // write output
+        File outputFile = new File(output);
+        if (outputFile.exists() && (!outputFile.delete())) {
+            throw new MojoExecutionException("Unable to delete file " + output);
+        }
+        try {
+            outputFile.getParentFile().mkdirs();
+            if (!outputFile.createNewFile()) {
+                throw new MojoExecutionException("Unable to create file " + output);
+            }
+        } catch (IOException ioe) {
+            throw new MojoExecutionException("Unable to create file " + output, ioe);
+        }
+        return outputFile;
+    }
+
+    private String toSignature(String identifier) {
+        StringBuilder aString = new StringBuilder();
+        char[] chars = identifier.toCharArray();
+        int index = 0;
+        boolean first = true;
+        while (index < chars.length) {
+            int begin;
+            while (Character.isWhitespace(chars[index])) {
+                index++;
+                if (index == chars.length) {
+                    break;
+                }
+            }
+            if (index == chars.length) {
+                break;
+            }
+            begin = index;
+            while (!Character.isWhitespace(chars[index])) {
+                index++;
+                if ((index == chars.length) || SIG_SPECIAL_CHARS.contains(chars[index - 1])
+                        || ((index < chars.length - 1) && SIG_SPECIAL_CHARS.contains(chars[index]))) {
+                    break;
+                }
+            }
+            if (!first) {
+                aString.append(' ');
+            }
+            aString.append(new String(chars, begin, index - begin));
+            first = false;
+        }
+        return aString.toString();
+    }
+}
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/extension/grammar/GrammarExtensionMojoTest.java b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/extension/grammar/GrammarExtensionMojoTest.java
new file mode 100644
index 0000000..386c4f3
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/extension/grammar/GrammarExtensionMojoTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.extension.grammar;
+
+import java.io.File;
+
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.junit.Test;
+
+public class GrammarExtensionMojoTest extends AbstractMojoTestCase {
+
+    /**
+     * @throws Exception
+     */
+    @Test
+    public void testMojoGoal() throws Exception {
+        File testPom =
+                new File(getBasedir(), "src" + File.separator + "test" + File.separator + "resources" + File.separator
+                        + "unit" + File.separator + "basic-test" + File.separator + "basic-test-plugin-config.xml");
+        GrammarExtensionMojo mojo = (GrammarExtensionMojo) lookupMojo("grammarix", testPom);
+        assertNotNull(mojo);
+        mojo.execute();
+    }
+}
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/lang/extension/EchoStatement.java b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/lang/extension/EchoStatement.java
new file mode 100644
index 0000000..7c6e882
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/java/org/apache/asterix/lang/extension/EchoStatement.java
@@ -0,0 +1,47 @@
+/*
+ * 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.lang.extension;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+
+public class EchoStatement implements Statement {
+
+    private final String arg;
+
+    public EchoStatement(String arg) {
+        this.arg = arg;
+    }
+
+    @Override
+    public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws AsterixException {
+        return null;
+    }
+
+    @Override
+    public byte getKind() {
+        return -1;
+    }
+
+    public String getArg() {
+        return arg;
+    }
+
+}
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/lang/extension.jj b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/lang/extension.jj
new file mode 100644
index 0000000..2106e4d
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/lang/extension.jj
@@ -0,0 +1,45 @@
+import org.apache.asterix.lang.extension.EchoStatement;
+
+// Merging of non-terminals can only be done on non-terminals which conform to the following structure.
+// Content will simply be prepended or appended to the base blocks.
+// Note: refrain from using the strings "before:" and "after:" in the merge areas as that will break the merge.
+// As a workaround, you can always override
+@merge
+Statement SingleStatement() throws ParseException:
+{
+  // merge area 1
+  before:
+  after:
+}
+{
+  (
+    // merge area 2
+    before:
+    after:    | stmt = EchoStatement())
+  {
+    // merge area 3
+  }
+}
+
+// The default
+// Adding a new node. if a node exists, it will throw an exception.
+@new
+Statement EchoStatement() throws ParseException:
+{
+  String arg = null;
+}
+{
+  <ECHO> arg = Identifier()
+    {
+      return new EchoStatement(arg);
+    }
+}
+
+<DEFAULT,IN_DBL_BRACE>
+TOKEN :
+{
+    <ECHO : "echo">
+}
+
+// Overriding a non-terminal. if exists in base, it will be overriden, otherwise, it will be added
+// @override
diff --git a/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/unit/basic-test/basic-test-plugin-config.xml b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/unit/basic-test/basic-test-plugin-config.xml
new file mode 100644
index 0000000..b8253bb
--- /dev/null
+++ b/asterixdb/asterix-maven-plugins/asterix-grammar-extension-maven-plugin/src/test/resources/unit/basic-test/basic-test-plugin-config.xml
@@ -0,0 +1,80 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.asterix</groupId>
+        <artifactId>asterix-opt</artifactId>
+        <version>0.1-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.extension</groupId>
+    <artifactId>grammar-extension</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.asterix</groupId>
+            <artifactId>asterix-external-data</artifactId>
+            <version>0.8.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.couchbase.client</groupId>
+            <artifactId>core-io</artifactId>
+            <version>1.2.8</version>
+        </dependency>
+        <dependency>
+            <groupId>io.reactivex</groupId>
+            <artifactId>rxjava</artifactId>
+            <version>1.0.15</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.asterix</groupId>
+                <artifactId>asterix-grammar-extension-maven-plugin</artifactId>
+                <version>0.8.9-SNAPSHOT</version>
+                <configuration>
+                    <base>../../asterix-lang-aql/src/main/javacc/AQL.jj</base>
+                    <extension>src/test/resources/lang/extension.jj</extension>
+                    <output>target/generated-sources/lang/grammar.jj</output>
+                    <parserClassName>ExtendedParser</parserClassName>
+                    <packageName>org.apache.asterix.lang.extension.parser</packageName>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>grammarix</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+            <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.asterix</groupId>
+                                        <artifactId>asterix-grammar-extension-maven-plugin</artifactId>
+                                        <versionRange>[0.8.9-SNAPSHOT,)</versionRange>
+                                        <goals>
+                                            <goal>grammarix</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+</project>
\ No newline at end of file
diff --git a/asterixdb/asterix-maven-plugins/pom.xml b/asterixdb/asterix-maven-plugins/pom.xml
index 2623c64..9207abe 100644
--- a/asterixdb/asterix-maven-plugins/pom.xml
+++ b/asterixdb/asterix-maven-plugins/pom.xml
@@ -56,5 +56,6 @@
     <module>record-manager-generator-maven-plugin</module>
     <module>asterix-evaluator-generator-maven-plugin</module>
     <module>asterix-test-datagenerator-maven-plugin</module>
+    <module>asterix-grammar-extension-maven-plugin</module>
   </modules>
 </project>
\ No newline at end of file
diff --git a/asterixdb/asterix-tools/src/main/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java b/asterixdb/asterix-tools/src/main/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
index a5b8f48..a525b1b 100644
--- a/asterixdb/asterix-tools/src/main/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
+++ b/asterixdb/asterix-tools/src/main/java/org/apache/asterix/tools/translator/ADGenDmlTranslator.java
@@ -53,7 +53,7 @@
         typeDataGenMap = new HashMap<TypeSignature, TypeDataGen>();
 
         for (Statement stmt : aqlStatements) {
-            if (stmt.getKind() == Statement.TYPE_DECL) {
+            if (stmt.getKind() == Statement.Kind.TYPE_DECL) {
                 TypeDecl td = (TypeDecl) stmt;
                 String typeDataverse =
                         td.getDataverseName() == null ? defaultDataverse : td.getDataverseName().getValue();
@@ -73,7 +73,7 @@
 
     private String getDefaultDataverse() {
         for (Statement stmt : aqlStatements) {
-            if (stmt.getKind() == Statement.DATAVERSE_DECL) {
+            if (stmt.getKind() == Statement.Kind.DATAVERSE_DECL) {
                 return ((DataverseDecl) stmt).getDataverseName().getValue();
             }
         }