package org.latexlab.clsi.client.remote;
import java.util.Date;
import org.latexlab.clsi.client.ClsiService;
import org.latexlab.clsi.client.TimeoutException;
import org.latexlab.clsi.client.async.CompileCallback;
import org.latexlab.clsi.client.protocol.ClsiResourceReference;
import org.latexlab.clsi.client.protocol.ClsiServiceCompileResponse;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.dom.client.ScriptElement;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
/**
* CLSI service.
*/
public class ClsiRemoteService extends ClsiService {
private String serviceUrl, asyncPath;
private ScriptElement link;
private FormPanel form;
private Timer timer;
private CompileCallback handler;
private int timeout = 60, elapsed = 0;
public ClsiRemoteService() {
form = new FormPanel();
form.setVisible(false);
RootPanel.get().add(form);
initialize(this);
}
public ClsiRemoteService(int timeout, String serviceUrl, String asyncPath, String token, String id) {
super(token, id);
this.serviceUrl = serviceUrl;
this.asyncPath = asyncPath;
this.timeout = timeout;
initialize(this);
}
public String getServiceUrl() {
return serviceUrl;
}
public void setServiceUrl(String serviceUrl) {
this.serviceUrl = serviceUrl;
}
public String getAsyncPath() {
return asyncPath;
}
public void setAsyncPath(String asyncPath) {
this.asyncPath = asyncPath;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public void compile(String name, String contents, String primaryResource,
ClsiResourceReference[] resources, String compiler, String format,
CompileCallback callback) {
try {
instance++;
handler = callback;
String request = buildCompileRequest(
name, contents, primaryResource, resources, compiler, format);
Hidden field = new Hidden();
field.setName("request");
field.setValue(request);
VerticalPanel formContents = new VerticalPanel();
formContents.add(field);
form.reset();
form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
elapsed = 0;
detectResponse(instance);
}
});
FormElement.as(form.getElement()).setAcceptCharset("UTF-8");
form.setWidget(formContents);
form.setMethod(FormPanel.METHOD_POST);
form.setAction(serviceUrl);
form.submit();
} catch (Exception x) {
handler.onFailure(x);
}
}
private void detectResponse(int instance) {
if (timer != null) {
timer.cancel();
}
timer = new Timer() {
public void run() {
elapsed ++;
if (elapsed > timeout) {
timer.cancel();
elapsed = 0;
if (handler != null) {
handler.onFailure(new TimeoutException("The compile operation exceeded the allowed " + timeout + " seconds timeout value."));
}
} else {
checkResponse();
}
}
};
timer.scheduleRepeating(1000);
}
private void checkResponse() {
if (!asyncPath.endsWith("/")) {
asyncPath += "/";
}
String src = asyncPath.replace("<token>", this.token).replace("<id>", this.id) + "response.js?r=" + (new Date()).getTime();
if (link != null) {
link.removeFromParent();
}
Document doc = Document.get();
link = doc.createScriptElement();
link.setSrc(src);
link.setType("text/javascript");
doc.getBody().appendChild(link);
}
private static final native void initialize(ClsiRemoteService obj) /*-{
$wnd.clsi_oncompile = function(r) {
obj.@org.latexlab.clsi.client.remote.ClsiRemoteService::onResponse(Lorg/latexlab/clsi/client/protocol/ClsiServiceCompileResponse;)(r);
}
}-*/;
public void onResponse(ClsiServiceCompileResponse resp) {
if (timer != null) {
timer.cancel();
}
if (handler != null) {
CompileCallback cb = handler;
handler = null;
cb.onSuccess(resp);
}
}
}