Index: gs3-extensions/meandre/trunk/src/web/meandre-controller.js
===================================================================
--- gs3-extensions/meandre/trunk/src/web/meandre-controller.js	(revision 28547)
+++ gs3-extensions/meandre/trunk/src/web/meandre-controller.js	(revision 28547)
@@ -0,0 +1,303 @@
+
+// Examples of how to control a Meandre Infrastructure (running on default port of 1714)
+
+//  http://localhost:1714/services/execute/flow.txt?statistics=true&uri=http://greenstone.org/meandre/flows/chromagram-v3/&token=abc
+//    => Runs the specified flow, 
+//    => gives the Infrastructure a token to identify the given running instance
+
+//  http://localhost:1714/services/execute/uri_flow.txt?statistics=true&token=abc
+//    => Uses the 'token' to glean values of the running instance, such as which port it is using
+//    => Reponse is plain text in value-pair form of properties
+
+
+//  http://localhost:1718/http://greenstone.org/meandre/flows/chromagram-v3/instance/greenstone-doc-id-service-to-signal/0?cmd=generate-audio-signal&docOID=abc
+//    => Contacts the specified component in the running workflow
+//    => Note: the port used (1718) is the value returned from using 'uri_flow.txt' above
+//    =>       The URI given to the server on this port is the full URI 'name' shown in the Meandre Workbench for this components 
+
+
+
+var MeandreController = function(webDomain, infrastructurePort, workbenchPort) 
+{
+    this.proxyURL = "/greenstone3/cgi-bin/meandre-proxy.pl";
+
+    this.webDomain = webDomain || "http://localhost";
+
+    this.infrastructurePort = (infrastructurePort || "1714");
+    this.workbenchPort      = (workbenchPort || "1712");
+    this.infrastructureBaseURL = this.webDomain + ":" + this.infrastructurePort;
+
+    this.workbenchURL          = this.webDomain + ":" + this.workbenchPort + "/Workbench.html";
+    
+    this.initiateFlowServlet = "/services/execute/flow.txt";
+    this.runningFlowServlet  = "/services/execute/uri_flow.txt";
+    this.abortFlowServlet    = "/admin/abort.txt";
+
+};
+
+
+MeandreController.prototype.runFlow = function(flowURL) {
+
+    console.log("**** using hardwired username of 'admin' for now");
+    var username = "admin";
+
+    var timestamp = new Date().getTime();
+    var token = username + "_" + timestamp;
+
+    var url = this.infrastructureBaseURL + this.initiateFlowServlet + "?statistics=true&uri=" + flowURL + "&token=" + token;
+    var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url);
+
+    // Callback called when flow naturally finishes, or is stopped through an abort command
+    var request = $.ajax({
+	url: proxiedURL,
+	cache: false
+    });
+    
+    request.done(function(text) {
+	console.info( "Meandre Flow completed for URL: " + url);
+    });
+
+    request.fail(function(jqXHR, textStatus) {
+	alert( "Request for URL:\n\n    " + url + "\n\nfailed: " + textStatus + "\n--------\n" + jqXHR.statusText );
+    });
+
+    return token;
+};
+
+
+
+MeandreController.prototype.optionsToArgs = function(options) {
+
+    var args = null;
+
+    // nice if this could be done as a one-liner with 'join()'
+    for (var k in options){
+	if (args==null) {
+	    args = "";
+	}
+	else {
+	    args += "&";
+	}
+
+	args += k + "=" + options[k];
+    }
+
+    return args;
+}
+
+MeandreController.prototype.webComponentToURL = function(webDomain,port,webComp,options) {
+
+    var args = this.optionsToArgs(options);
+
+    var url = webDomain + ":" + port;
+
+    if (webComp.indexOf("/") != 0) {
+	url += "/";
+    }
+    url += webComp + "?" + args;
+
+    return url;
+}
+
+function valuePairsTextToPropertyTable(text) {
+
+    var lines = text.split("\n");
+
+    for (var i=0; i<lines.length; i++) {
+	var line = lines[i];
+	
+	var pair = line.match(/\s*(\w+)\s*=\s*(.*?)\s*$/);
+	
+	if ((pair!=null) && (pair.length==3)) {
+	    var metaname = pair[1];
+	    var metaval  = pair[2];
+	    
+	    // console.log("**** storing '"+metaname+"' = '" + metaval +"'");
+	    
+	    this[metaname] = metaval;
+	}
+    }
+
+    //return props;
+}
+
+MeandreController.prototype.webComponentProperties = function(port,webComp,options) {
+
+/*
+    var args = this.optionsToArgs(options);
+
+    var url = this.webDomain + ":" + port;
+
+    if (webComp..indexOf("/") != 0) {
+	url = + "/";
+    }
+    url += webComp + "?" + args;
+*/
+
+    var url = this.webComponentToURL(this.webDomain,port,webComp,options);
+
+    // make *synchronous* call, and parse the returned text file as value-pairs
+
+    var props = {};
+
+    var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url);
+
+    var request = $.ajax({
+	url: proxiedURL,
+	context: props,
+	async: false,
+	cache: false
+    });
+
+    request.done(valuePairsTextToPropertyTable);
+
+/*
+function (text) {
+
+	var lines = text.split("\n");
+	for (var i=0; i<lines.length; i++) {
+	    var line = lines[i];
+
+	    var pair = line.match(/\s*(\w+)\s*=\s*(.*?)\s*$/);
+
+	    if ((pair!=null) && (pair.length==3)) {
+		var metaname = pair[1];
+		var metaval  = pair[2];
+		
+		// console.log("**** storing '"+metaname+"' = '" + metaval +"'");
+		
+		props[metaname] = metaval;
+	    }
+	}
+    });
+*/
+
+    request.fail(function(jqXHR, textStatus) {
+	console.error( "Request for URL:\n\n    " + url + "\n\nfailed: " +  + textStatus + "\n--------\n" + jqXHR.statusText );
+    });
+
+    return props;
+};
+
+
+MeandreController.prototype.webComponent = function(port,webComp,options) {
+
+    var payload = null;
+
+    var url = this.webComponentToURL(this.webDomain,port,webComp,options);
+
+    var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url);
+
+//    console.log("**** proxiedURL = " + proxiedURL);
+
+    // Synchronous call to return returned output from URL
+    var request = $.ajax({
+	url: proxiedURL,
+	async: false,
+	cache: false
+    });
+    
+    request.done(function(output) {	
+	console.info( "Response of " + output.length + " bytes from URL: " + url + " received");
+	payload = output;
+    });
+
+    request.fail(function(jqXHR, textStatus) {
+	alert( "Request for URL:\n\n    " + url + "\n\nfailed: " +  textStatus + "\n--------\n" + jqXHR.statusText );
+    });
+
+    return payload;
+};
+
+
+
+MeandreController.prototype.binaryWebComponent = function(port,webComp,options, callback, context) {
+
+    var payload = { data: null };
+/*
+    var args = optionsToArgs(options);
+
+    var url = this.webDomain + ":" + port + "/" + webComp + "?" + args;
+*/
+
+    var url = this.webComponentToURL(this.webDomain,port,webComp,options);
+
+    //console.log("binaryWebComponent: url = " + url);
+
+    var timestamp = new Date().getTime();
+    var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url) + "&_=" + timestamp;
+
+    // See if possible to do the same with jquery's ajax method ?? // ****
+
+    var oReq = new XMLHttpRequest();
+    oReq.open("GET",proxiedURL, true);
+    oReq.responseType = "arraybuffer";
+
+    oReq.onload = function (oEvent) { callback.call(context,oEvent,oReq) };
+
+/*
+    oReq.onload = function (oEvent) {
+
+	var arrayBuffer = oReq.response; // Note: not oReq.responseText
+
+	if (arrayBuffer.byteLength) {
+	    console.log("*** Recieved binary data: raw byte array buffer len = " + arrayBuffer.byteLength);
+
+	    var float32Array = new Float32Array(arrayBuffer); 
+
+	    payload.data = float32Array;
+	}
+    };
+*/
+
+    oReq.send(null);
+
+    return payload;
+
+};
+
+
+MeandreController.prototype.runningFlowProperties = function(token) {
+
+    var port    = this.infrastructurePort;
+    var webComp = this.runningFlowServlet;
+    var options = { statistics: true, token: token };
+
+    var props = this.webComponentProperties(port,webComp,options);
+
+    return props;
+};
+
+
+MeandreController.prototype.abortFlow = function(port) {
+
+    var url = this.webDomain + ":" + port + this.abortFlowServlet;
+
+    var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url);
+
+    // Asynchronous call to stop the given flow
+    var request = $.ajax({
+	url: proxiedURL
+    });
+    
+    request.done(function(text) {
+	console.info( "Request to abort Meandre Flow for URL: " + url + " issued");
+    });
+
+    request.fail(function(jqXHR, textStatus) {
+	alert( "Request for URL:\n\n    " + url + "\n\nfailed: " +  textStatus + "\n--------\n" + jqXHR.statusText );
+    });
+
+};
+
+MeandreController.prototype.loadWorkbench = function(frameId,workflowPos) {
+
+    var url = this.workbenchURL + "?" + "displayMode=compact&workflowPos=" + workflowPos;
+    //var proxiedURL = this.proxyURL + "?" + encodeURIComponent(url);
+
+    $('#'+frameId).attr("src",url);
+
+    //$('#'+frameId).attr("src",proxiedURL);
+
+}
+
