diff --git a/doc/demo/.gitignore b/doc/demo/.gitignore index 51554c4de..c8e2ad254 100644 --- a/doc/demo/.gitignore +++ b/doc/demo/.gitignore @@ -1,6 +1,6 @@ qcertJS.js qcert-runtime.js demo.js -qcertPreCompiler.js +qcertWhiskDispatch.js *.js.map node_modules/ diff --git a/doc/demo/demo.html b/doc/demo/demo.html index 04071fe6f..3ca901e32 100644 --- a/doc/demo/demo.html +++ b/doc/demo/demo.html @@ -137,7 +137,7 @@

Please select an input language by placing a language block on top of the st - + diff --git a/doc/demo/demo.ts b/doc/demo/demo.ts index cb8e3efea..845fdcf40 100644 --- a/doc/demo/demo.ts +++ b/doc/demo/demo.ts @@ -113,7 +113,7 @@ interface PuzzleSides { theTextArea.value = resultPack.result; } - qcertPreCompile({ + qcertWhiskDispatch({ source:path[0], target:path[path.length-1], path:middlePath, @@ -2768,12 +2768,7 @@ function completeCSVs(readFiles) { return; } let delimiter = (document.getElementById("delimiter")).value; - let schema = JSON.parse(schemaText); - let toSend = JSON.stringify({schema: schema, delimiter: delimiter, data: readFiles}); - let process = function(result) { - getExecInputArea().value = result; - } - preProcess(toSend, "csv2JSON", process); + getExecInputArea().value = JSON.stringify({delimiter: delimiter, data: readFiles}); } function handleOptimFile(files:FileList) { @@ -2828,41 +2823,13 @@ function handleFile(output:string, isSchema:boolean, files:FileList) { } else { reader.onload = function(event) { const contents:string = (event.target).result; - if (isSchema && isSQLSchema(contents)) - convertSQLSchema(contents, outputElem); - else - outputElem.value = contents; + outputElem.value = contents; } reader.readAsText(file); } } } -// Determine if a String contains a SQL schema. Not intended to be foolproof but just to discriminate the two supported schema -// notations (SQL and JSON) when the input is at least mostly valid. -function isSQLSchema(schemaText:string) : boolean { - /* A SQL schema should have the word "create" in it but SQL is case insensitive */ - var create = schemaText.search(/create/i); - if (create < 0) - return false; - var brace = schemaText.indexOf('{'); - if (brace >= 0 && brace < create) - /* Word create is coincidentally appearing inside what is probably a JSON schema */ - return false; - /* Looking more like SQL. Drop any blanks that follow 'create' */ - var balance = schemaText.substring(create + 6).trim(); - /* The next word must be 'table' (case insensitive) */ - var table = balance.search(/table/i); - return table == 0; -} - -function convertSQLSchema(toConvert:string, outputElem:HTMLTextAreaElement) { - var process = function(result:string) { - outputElem.value = result; - } - var result = preProcess(toConvert, "sqlSchema2JSON", process); -} - function handleFileDrop(output:string, event:DragEvent) { event.stopPropagation(); event.preventDefault(); diff --git a/doc/demo/evalWorker.js b/doc/demo/evalWorker.js index 181139aa3..7fdcfc5b1 100644 --- a/doc/demo/evalWorker.js +++ b/doc/demo/evalWorker.js @@ -20,7 +20,7 @@ // is going on too long. // Get dependencies. We put our merged runtime functions at global scope so they are available to the query -importScripts("qcert-runtime.js", "qcertPreCompiler.js", "qcertJS.js"); +importScripts("qcert-runtime.js", "qcertWhiskDispatch.js", "qcertJS.js"); // Here upon receiving the activation message from the main thread. This has two possible forms. // 1. An array of Strings containing inputText, schemaText, and compiledQuery (requesting Javascript execution). @@ -47,7 +47,7 @@ function qcertEval(inputConfig) { // Each spawned worker is designed to be used once close(); } - qcertPreCompile(inputConfig, handler); + qcertWhiskDispatch(inputConfig, handler); } // Javascript evaluation diff --git a/doc/demo/qcert.html b/doc/demo/qcert.html index ccd3c702c..141eacc72 100644 --- a/doc/demo/qcert.html +++ b/doc/demo/qcert.html @@ -4,7 +4,7 @@ Q*cert online form - + diff --git a/doc/demo/qcertPreCompiler.ts b/doc/demo/qcertPreCompiler.ts deleted file mode 100644 index 22e70ee94..000000000 --- a/doc/demo/qcertPreCompiler.ts +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (C) 2016-2017 Joshua Auerbach - * - * Licensed 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. - */ - -// List server hosts in the order they should be attempted. It is a good idea (but not required) to put localhost first so that -// new functionality can be tested without updating remote server hosts. The list can contain two distinct string formats. -// (1) A string that does not contain forward slashes is assumed to be a host name or -// address and a long-running server is assumed to be at that host on port 9879. -// (2) A string containing forward slashes is assumed to be a URL; the URL is used to invoke a whisk web action providing the server -// functionality. -// NOTE: the usually-available long-running server at 35.164.159.76 is currently listed AHEAD of the whisk action. To test the whisk -// action, change the order. The long-running server will probably be switched off once we have confidence in the whisk action. - -var serverHosts = [ - "localhost", - "35.164.159.76", - "https://openwhisk.ng.bluemix.net/api/v1/web/JoshAuerbachThoughts_test/default/qcertJavaService.json", - ]; - -function preProcess(text: string, verb: string, callback: (result: string) => any) { - var next = function() { - callback("ERROR: no server found to process " + verb + " request"); - } - for (var i = serverHosts.length - 1; i >=0; i--) - next = makeHandler(text, verb, serverHosts[i], callback, next); - next(); -} - -function makeHandler(text: string, verb: string, host: string, success: (result: string) => any, failure: () => any) { - return function() { - console.log("Handler invoked for host " + host); - var whisk = false; - var url; - if (host.indexOf('/') > 0) { - whisk = true; - url = host; - text = whiskify(verb, text); - } else - url = "http://" + host + ":9879?verb=" + verb; - var request = new XMLHttpRequest(); - request.open("POST", url, true); - request.setRequestHeader("Content-Type", whisk ? "application/json" : "text/plain"); - request.onloadend = function() { - if (request.status == 200) { - console.log("Success with verb " + verb + " at host " + host); - var response = whisk ? dewhiskify(request.responseText) : request.responseText; - success(response); - } else { - console.log("Failure with verb " + verb + " at host " + host); - failure(); - } - } - try { - console.log("Sending request to host " + host); - request.send(text); - } catch (e) { - } - } -} - -function whiskify(verb: string, text: string) { - return JSON.stringify({verb: verb, arg: text}); -} - -function dewhiskify(response: string) { - var obj = JSON.parse(response); - return obj.response; -} - -function combineInputAndSchema(input: string, schema: string) { - var parsed = JSON.parse(schema); - var combined = { source: input, schema: parsed }; - return JSON.stringify(combined); -} - -function qcertPreCompile(input: QcertCompilerConfig, callback: (result: QcertResult) => any) { - var verb = null, sourceCAMP = false, query = null; - console.log("Starting pre-compile for source language " + input.source); - if (input.source == "sql") { - verb = "parseSQL"; - sourceCAMP = false; - query = input.query; - } else if (input.source == "sqlpp") { - verb = "parseSQLPP"; - sourceCAMP = false; - query = input.query; - } else if (input.source == "tech_rule") { - verb = "techRule2CAMP"; - sourceCAMP = true; - query = combineInputAndSchema(input.query, input.schema); - } else if (input.source == "designer_rule") { - verb = "serialRule2CAMP"; - sourceCAMP = true; - query = input.query; - } else { - console.log("No precompile, synchronous callback"); - callback(qcertCompile(input)); - return; - } - if (query.length == 0) { - callback({ result: "ERROR: No source query provided", eval: undefined, emit: null, emitall: []}); - return - } - var handler = function(result: string) { - if (result.substring(0, 6) == "ERROR:") { - console.log("Calling back with error: " + result); - callback({ result: result, eval: undefined, emit: null, emitall: []}); - } else { - input.query = result; - input.sourcesexp = true; - if (sourceCAMP) { - input.source = "camp_rule"; - if (input.path[0].toLowerCase() == "camp_rule") - input.path.shift(); - } - console.log("Doing qcertCompile after successful preProcess"); - console.log("Path: " + input.path); - callback(qcertCompile(input)); - } - } - console.log("Dispatching preprocess"); - preProcess(query, verb, handler); -} diff --git a/doc/demo/qcertScripts.js b/doc/demo/qcertScripts.js index 02f667b13..0fa642e0e 100644 --- a/doc/demo/qcertScripts.js +++ b/doc/demo/qcertScripts.js @@ -39,7 +39,7 @@ function compileButton() { document.getElementById("result").innerHTML = escapeHtml(compiledQuery); displayAllResults(compilationResult.emitall); } - qcertPreCompile(input, handler); + qcertWhiskDispatch(input, handler); } function verify(result, expected) { result = result[0]; // TODO is this always right? @@ -76,7 +76,7 @@ function compileForEval() { evalQuery = compilationResult.eval; document.getElementById("execresult").innerHTML = escapeHtml(evalQuery); } - qcertPreCompile(input, handler); + qcertWhiskDispatch(input, handler); } function performJsEvaluation() { // Processing is delegated to a web-worker diff --git a/doc/demo/qcertWhiskDispatch.ts b/doc/demo/qcertWhiskDispatch.ts new file mode 100644 index 000000000..09d9acd6b --- /dev/null +++ b/doc/demo/qcertWhiskDispatch.ts @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2016-2017 Joshua Auerbach + * + * Licensed 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. + */ + +// List URLs for the "whisk" qcert service in the order they should be attempted. It is a good idea (but not required) to put a +// localhost URL first so that new functionality can be tested without perturbing publically deployed whisk actions. Note that +// our long-running server (what you would run on localhost) is not actually a whisk runtime; it just emulates enough of its behavior +// to run our two actions. + +var serverHosts = [ + "http://localhost:9879", + "https://openwhisk.ng.bluemix.net/api/v1/web/JoshAuerbachThoughts_test/qcert/qcert.json" + ]; + +function whiskDispatch(input: QcertCompilerConfig, callback: (result: QcertResult) => any) { + var next = function() { + console.log("No server found to process request, calling qcertJS.js directly"); + callback(qcertCompile(input)); + } + for (var i = serverHosts.length - 1; i >=0; i--) + next = makeHandler(input, serverHosts[i], callback, next); + next(); +} + +function makeHandler(input: QcertCompilerConfig, url: string, success: (result: QcertResult) => any, failure: () => any) { + return function() { + console.log("Handler invoked on URL " + url); + var request = new XMLHttpRequest(); + request.open("POST", url, true); + request.setRequestHeader("Content-Type", "application/json"); + request.onloadend = function() { + if (request.status == 200) { + console.log("Success at url " + url); + var response = JSON.parse(request.responseText); + success(response); + } else { + console.log("Failure at url " + url); + failure(); + } + } + try { + console.log("Posting request on url " + url); + request.send(JSON.stringify(input)); + } catch (e) { + } + } +} + +function qcertWhiskDispatch(input: QcertCompilerConfig, callback: (result: QcertResult) => any) { + var handler = function(result: QcertResult) { + if (result.result.substring(0, 6) == "ERROR:") + console.log("Calling back with error: " + result.result); + else + console.log("Calling back after success"); + callback(result); + } + console.log("Dispatching whiskDispatch"); + whiskDispatch(input, handler); +} diff --git a/doc/demo/tsconfig.json b/doc/demo/tsconfig.json index 325385f2c..3fda55dd7 100644 --- a/doc/demo/tsconfig.json +++ b/doc/demo/tsconfig.json @@ -11,7 +11,7 @@ "demo.ts", "typings.d.ts", "qcertJS.d.ts", - "qcertPreCompiler.ts" + "qcertWhiskDispatch.ts" ] }