Stable API for beta + legacy queries functional on Cherry
diff --git a/asterix-app/src/main/resources/sdk/static/js/asterix-api-core.js b/asterix-app/src/main/resources/sdk/static/js/asterix-api-core.js
index 69e6a6e..e98b2c9 100644
--- a/asterix-app/src/main/resources/sdk/static/js/asterix-api-core.js
+++ b/asterix-app/src/main/resources/sdk/static/js/asterix-api-core.js
@@ -15,8 +15,9 @@
         remote: {
             post: {}
         }
-    })
+    });
     
+
     // Asterix SDK => send
     // Posts a message containing an API endpoint, json data,
     // and a UI callback function.
@@ -30,15 +31,46 @@
     // var e = Expression;
     // var h = AsterixRestController.bindExpression(e);
     // a.send(h);
-    this.send = function(handler) {
-        var api = handler.onSend();
+    myThis = this;
+    this.callbacks = {
+        "sync" : function() { alert("default sync"); },
+        "async" : function() {}
+    };
+    this.send = function(handler, cb) {
+        myThis.callbacks = cb;
+        this.handler = handler;
+        this.extras = handler["extras"];
         this.xhr.post(
-            api["endpoint"],
-            api["apiData"],
-            api["callback"]
+            handler["endpoint"],
+            handler["apiData"],
+            this.branch          
         );
     };
 
+
+    // TODO DOC
+    this.branch = function(response) {
+        if (response && response["error-code"]) {
+           
+            alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
+            
+        } else if (response && response["results"]) {
+            var fn_callback = myThis.callbacks["sync"];
+            fn_callback(response, myThis.extras);
+            
+        } else if (response["handle"]) {
+            
+            var fn_callback = this.callbacks["async"];
+            fn_callback(response, extra);
+            
+        } else if (response["status"]) {
+                
+            var fn_callback = this.callbacks["sync"];
+            fn_callback(response, extra);
+        }
+    }
+
+        
     // Asterix SDK => requestHandler
     // Handlers remote requests to Asterix REST API
     // using the easyXDM RPC protocol
@@ -48,7 +80,7 @@
         var rpc = new easyXDM.Rpc({}, {
             local: {
                 post: {
-                    method: function(url, data, fn, fnError){
+                    method: function(url, data, fn, fnError){ 
                         $.ajax({
                             type : 'GET',
                             url : url,
@@ -63,8 +95,186 @@
             }
         });
     }
+
+
+    // Asterix SDK => bindingHandler
+    // AsterixExpression form handler where a new REST API point is bound. Takes as input any
+    // AsterixExpression, each of which is bindable.
+    this.bindingHandler = new AsterixExpression();
+    this.bind = this.bindingHandler.bind;
 }
 
+// AsterixExpression => Base AQL Syntax Class
+//
+// Components: 
+//      boundTo -> a "next" expression
+function AsterixExpression() {
+    this.boundTo = {};
+    this.value = "";
+    this.ui_callback_on_success = function() {};
+    this.ui_callback_on_success_async = function() {};
+}
+
+// AsterixExpression => bind
+//
+// Binds a "next" AsterixExpression to this one.
+//
+// @param expression [AsterixExpression] MUST be instanceof AsterixExpression
+// TODO Check if it has a bind method or things will get messy.
+AsterixExpression.prototype.bind = function(expression) {
+    // If expression is an AsterixExpression, it becomes base
+    if (expression instanceof AsterixExpression) {
+        this.boundTo = expression;
+    } else if (expression instanceof AsterixClause) {
+        alert("Clause");
+    }
+    return this;
+}
+
+// AsterixExpression => send
+//
+// @param arc [AsterixRESTController]
+// TODO: Arc parameter is temporary
+AsterixExpression.prototype.send = function(arc) {
+    // Hackiest of hacks
+    var g = new AsterixSDK();
+    g.send(arc, arc["callback"]);
+}
+
+// AsterixExpression => success
+//
+// @param method [FUNCTION]
+// @param isSynchronous [BOOLEAN]
+AsterixExpression.prototype.success = function(fn, isSync) {
+    if (isSync) {
+        this.ui_callback_on_success = fn;
+    } else { 
+        this.ui_callback_on_success_async = fn;
+    }
+};
+
+function CreateExpression() {} // "create" ( "type" | "nodegroup" | "external" <DATASET> | <DATASET> | "index" | "dataverse" 
+function FLWOGRExpression() {} // ( ForClause | LetClause ) ( Clause )* "return" Expression
+
+//TODO
+function LegacyExpression() {} // Legacy for old AsterixAPI version: handle hardcoded strings. Will phase out.
+
+inherit(CreateExpression, AsterixExpression);
+inherit(FLWOGRExpression, AsterixExpression);
+inherit(LegacyExpression, AsterixExpression);
+
+CreateExpression.prototype.set = function(statement) {
+    this.value = statement;
+};
+
+CreateExpression.prototype.send = function() {
+    myThis = this;
+    var arc = new AsterixRESTController();
+    arc.DDL(
+        { "ddl" : myThis.value },
+        {
+            "sync" : function () {}, // TODO This should be a default value out of the AsterixExpression base
+            "async" : function () {}
+        }
+    );
+
+    // Call AsterixExpression core send method
+    AsterixExpression.prototype.send.call(this, arc);
+};
+
+// LegacyExpression
+// Handles hardcoded query strings from prior versions
+// of this API. Can be useful for debugging.
+LegacyExpression.prototype.set = function(statement) {
+    this.value = statement;
+};
+
+LegacyExpression.prototype.get = function() {
+    return this.value;
+};
+
+LegacyExpression.prototype.send = function(endpoint, json) {
+    
+    var arc = {
+        "endpoint" : endpoint,
+        "apiData" : json, 
+        "callback" : {
+            "sync" : this.ui_callback_on_success,
+            "async" : this.ui_callback_on_success_async
+        },
+        "extras" : this.extras
+    };
+
+    AsterixExpression.prototype.send.call(this, arc);
+}
+
+LegacyExpression.prototype.extra = function(extras) {
+    this.extras = extras;
+}
+
+//
+// Clauses
+//
+function AsterixClause() {
+    this.clause = "";
+}
+
+AsterixClause.prototype.val = function() {
+    return this.clause;
+};
+
+function ForClause() {}     // "for" Variable ( "at" Variable )? "in" ( Expression )
+function LetClause() {}     // "let" Variable ":=" Expression
+function WhereClause() {}   // "where" Expression
+function OrderbyClause() {}   // ( "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )* )
+function GroupClause() {}     //  "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* 
+                            //      ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
+function LimitClause() {}     // "limit" Expression ( "offset" Expression )?
+function DistinctClause() {}  // "distinct" "by" Expression ( "," Expression )*
+
+inherit(ForClause, AsterixClause);
+inherit(LetClause, AsterixClause);
+inherit(WhereClause, AsterixClause);
+inherit(OrderbyClause, AsterixClause);
+inherit(GroupClause, AsterixClause);
+inherit(LimitClause, AsterixClause);
+inherit(DistinctClause, AsterixClause);
+
+ForClause.prototype.set = function() {
+
+    return this;
+};
+
+LetClause.prototype.set = function() {
+
+    return this;
+};
+
+WhereClause.prototype.set = function() {
+
+    return this;
+};
+
+OrderbyClause.prototype.set = function() {
+
+    return this;
+};
+
+GroupClause.prototype.set = function() {
+
+    return this;
+};
+
+LimitClause.prototype.set = function() {
+
+    return this;
+};
+
+DistinctClause.prototype.set = function()  {
+
+    return this;
+};
+
 // Asterix REST Controller
 //
 // Asterix REST Controller
@@ -138,7 +348,7 @@
 }
 
 
-
+//var a = AsterixSDK();
 
 function AsterixSDKJQueryHandler(json, endpoint, callback) {
     $.ajax({
@@ -153,27 +363,6 @@
 }
 
 
-function AsterixExpression() {}
-
-
-// Create expressions
-// Create types, dataverses, indexes
-CreateExpression.prototype = new AsterixExpression();
-CreateExpression.prototype.constructor = CreateExpression;
-function CreateExpression(statement) {
-    this.value = statement;
-    this.send = this.onSend;
-}
-CreateExpression.prototype.onSend = function () {
-    var arc = new AsterixRESTController();
-    myThis = this;
-    arc.DDL( 
-        { "ddl" : myThis.value },
-        function () {}
-    );
-    return arc;
-};
-
 
 // ForClause
 //
@@ -203,6 +392,18 @@
 }
  
 
+///////////////
+// Utilities //
+///////////////
+
+// Inherit with the proxy pattern
+// Source: https://gist.github.com/jeremyckahn/5552373
+function inherit(inherits, inheritsFrom) {
+    function proxy() {};
+    proxy.prototype = inheritsFrom.prototype;
+    inherits.prototype = new proxy();
+}
+
 /*
 // ************************
 // Asterix Query Manager
diff --git a/asterix-examples/src/main/resources/cherry/js/cherry.js b/asterix-examples/src/main/resources/cherry/js/cherry.js
index 8dd4524..0715ffe 100755
--- a/asterix-examples/src/main/resources/cherry/js/cherry.js
+++ b/asterix-examples/src/main/resources/cherry/js/cherry.js
@@ -1,5 +1,7 @@
 $(function() {	
 	    
+    APIHandler = new AsterixSDK();
+
     APIqueryTracker = {};
     drilldown_data_map = {};
     drilldown_data_map_vals = {};
@@ -252,17 +254,21 @@
 		    })
 		    .aql_return({ "cell" : "$c", "count" : "count($t)" });
 		    
-		// Here is an actual API call.
-		var asterixAPICall = new AsterixCoreAPI()
-		    .dataverse("twitter")
-		    .statements(buildCherryQuery.parameters["statements"])
-		    .mode(build_cherry_mode)
-		    .success(cherryQuerySyncCallback, true)
-		    .success(cherryQueryAsyncCallback, false)
-		    .add_extra("payload", formData) // Legacy
-		    .add_extra("query_string", buildCherryQuery.parameters["statements"].join(" ")) // Legacy
-		    .api_core_query(); 
-
+        var l = new LegacyExpression();
+        l.extra({
+            "payload" : formData,
+            "query_string" : "use dataverse twitter;\n" + buildCherryQuery.parameters["statements"].join("\n")
+        });
+        l.set(buildCherryQuery.parameters["statements"].join("\n"));
+		l.success(cherryQuerySyncCallback, true);
+		l.success(cherryQueryAsyncCallback, false);
+        
+        l.send("http://localhost:19101/query", 
+            {
+                "query" : "use dataverse twitter;\n" + buildCherryQuery.parameters["statements"].join("\n"),
+                "mode" : build_cherry_mode, 
+            });
+        
 		APIqueryTracker = {
 		    "query" : buildCherryQuery.parameters["statements"].join("\n"),
 		    "data" : formData
diff --git a/asterix-examples/src/main/resources/html/example.html b/asterix-examples/src/main/resources/html/example.html
index 01f6ed0..f0373ff 100644
--- a/asterix-examples/src/main/resources/html/example.html
+++ b/asterix-examples/src/main/resources/html/example.html
@@ -11,6 +11,8 @@
                 var c = new CreateExpression(tinySocialCreate.join("\n"));
                 as.send(c);
 
+                var as = new AsterixSDK();
+
                 $('#ddl').html(tinySocialCreate.join("<br/>"));
             });
         </script>