package water.api; import dontweave.gson.JsonArray; import dontweave.gson.JsonElement; import dontweave.gson.JsonObject; import water.DKV; import water.Job; import water.Job.JobState; import water.Key; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.ParseException; import java.util.Date; public class Jobs extends Request { Jobs() { } public static Response redirect(JsonObject resp, Key dest) { JsonObject redir = new JsonObject(); redir.addProperty(KEY, dest.toString()); return Response.redirect(resp, Jobs.class, redir); } @Override protected Response serve() { JsonObject result = new JsonObject(); JsonArray array = new JsonArray(); Job[] jobs = Job.all(); for( int i = jobs.length - 1; i >= 0; i-- ) { JsonObject json = new JsonObject(); json.addProperty(KEY, jobs[i].self().toString()); json.addProperty(DESCRIPTION, jobs[i].description); json.addProperty(DEST_KEY, jobs[i].dest() != null ? jobs[i].dest().toString() : ""); json.addProperty(START_TIME, RequestBuilders.ISO8601.get().format(new Date(jobs[i].start_time))); long end = jobs[i].end_time; JsonObject jobResult = new JsonObject(); Job job = jobs[i]; boolean cancelled; if (cancelled = (job.state==JobState.CANCELLED || job.state==JobState.FAILED)) { if(job.exception != null){ jobResult.addProperty("exception", "1"); jobResult.addProperty("val", jobs[i].exception); } else { jobResult.addProperty("val", "CANCELLED"); } } else if (job.state==JobState.DONE) jobResult.addProperty("val", "OK"); json.addProperty(END_TIME, end == 0 ? "" : RequestBuilders.ISO8601.get().format(new Date(end))); json.addProperty(PROGRESS, job.state==JobState.RUNNING || job.state==JobState.DONE ? jobs[i].progress() : -1); json.addProperty(PROGRESS, end == 0 ? (cancelled ? -2 : jobs[i].progress()) : (cancelled ? -2 : -1)); json.addProperty(CANCELLED, cancelled); json.add("result",jobResult); array.add(json); } result.add(JOBS, array); Response r = Response.done(result); r.setBuilder(JOBS, new ArrayBuilder() { @Override public String caption(JsonArray array, String name) { return ""; } }); r.setBuilder(JOBS + "." + KEY, new ArrayRowElementBuilder() { @Override public String elementToString(JsonElement elm, String contextName) { String html; if( !Job.isRunning(Key.make(elm.getAsString())) ) html = "<button disabled class='btn btn-mini'>X</button>"; else { String keyParam = KEY + "=" + elm.getAsString(); html = "<a href='/Cancel.html?" + keyParam + "'><button class='btn btn-danger btn-mini'>X</button></a>"; } return html; } }); r.setBuilder(JOBS + "." + DEST_KEY, new ArrayRowElementBuilder() { @Override public String elementToString(JsonElement elm, String contextName) { String str = elm.getAsString(); String key = null; try { key = URLEncoder.encode(str,"UTF-8"); } catch( UnsupportedEncodingException e ) { key = str; } return ("".equals(key) || DKV.get(Key.make(str)) == null) ? key : Inspector.link(str, str); } }); r.setBuilder(JOBS + "." + START_TIME, new ArrayRowElementBuilder() { @Override public String elementToString(JsonElement elm, String contextName) { return date(elm.toString()); } }); r.setBuilder(JOBS + "." + END_TIME, new ArrayRowElementBuilder() { @Override public String elementToString(JsonElement elm, String contextName) { return date(elm.toString()); } }); r.setBuilder(JOBS + "." + PROGRESS, new ArrayRowElementBuilder() { @Override public String elementToString(JsonElement elm, String contextName) { return progress(Float.parseFloat(elm.getAsString())); } }); r.setBuilder(JOBS + "." + "result", new ElementBuilder() { @Override public String objectToString(JsonObject obj, String contextName) { if(obj.has("exception")){ String rid = Key.make().toString(); String ex = obj.get("val").getAsString().replace("'", ""); String [] lines = ex.split("\n"); StringBuilder sb = new StringBuilder(lines[0]); for(int i = 1; i < lines.length; ++i){ sb.append("\\n" + lines[i]); } // ex = ex.substring(0,ex.indexOf('\n')); ex = sb.toString(); String res = "\n<a onClick=\"" + "var showhide=document.getElementById('" + rid + "');" + "if(showhide.innerHTML == '') showhide.innerHTML = '<pre>" + ex + "</pre>';" + "else showhide.innerHTML = '';" + "\">FAILED</a>\n<div id='"+ rid +"'></div>\n"; return res; } else if(obj.has("val")){ return obj.get("val").getAsString(); } return ""; } @Override public String build(String elementContents, String elementName) { return "<td>" + elementContents + "</td>"; } }); return r; } private static String date(String utc) { if( utc == null || utc.length() == 0 ) return ""; utc = utc.replaceAll("^\"|\"$",""); if( utc.length() == 0 ) return ""; long ms; try { ms = RequestBuilders.ISO8601.get().parse(utc).getTime(); } catch( ParseException e ) { throw new RuntimeException(e); } return "<script>document.write(new Date(" + ms + ").toLocaleTimeString())</script>"; } private static String progress(float value) { int pct = (int) (value * 100); String type = "progress-stripped active"; if (pct==-100) { // task is done pct = 100; type = "progress-success"; } else if (pct==-200) { pct = 100; type = "progress-warning"; } // @formatter:off return "" + "<div style='margin-bottom:0px;padding-bottom:0xp;margin-top:8px;height:5px;width:180px' class='progress "+type+"'>" // + "<div class='bar' style='width:" + pct + "%;'>" // + "</div>" // + "</div>"; // @formatter:on } @Override public RequestServer.API_VERSION[] supportedVersions() { return SUPPORTS_V1_V2; } }