source: cows_wps/trunk/cows_wps/controllers/jobviewer.py @ 6910

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows_wps/trunk/cows_wps/controllers/jobviewer.py@6910
Revision 6910, 8.0 KB checked in by astephen, 9 years ago (diff)

fixes

Line 
1import os
2import re
3import glob
4import logging
5import urllib
6import xml.etree.ElementTree as ET
7
8from pylons import request, response, session, tmpl_context as c
9from pylons.controllers.util import abort, redirect_to
10from routes import url_for
11
12
13from cows.exceptions import *
14from cows.pylons.ows_controller import render_ows_exception
15
16from cows_wps.controllers import *
17from cows_wps import utils
18from cows_wps.renderer.ui_renderer import *
19from cows_wps.model.managers import requestManager
20from cows_wps.process_handler.context.process_context import ProcessContext
21from cows_wps.renderer import xml_renderer
22
23from cows_wps.utils.parse_wps_config import wps_config_dict
24from cows_wps.utils.parse_capabilities_config import caps_config_dict
25
26
27from cows_wps.model.managers import requestManager
28
29log = logging.getLogger(__name__)
30
31
32class JobviewerController(BaseController):
33
34
35    def index(self):
36        status_url = str(request.params.getone("status_url"))
37#        job_id = str(request.params.getone("job_id"))
38        getter = urllib.urlopen(status_url)
39        job_xml = getter.read()
40        getter.close()
41 
42        job_as_table = self._xmlToTable(job_xml)
43        job_xml_encoded = self._htmlifyXML(job_xml)
44        job_as_plots = "There are no plots available in the outputs of this job."
45
46        resp = """<div id="view_options" style="background: #EEF4FF; border: 2px outset blue; padding: 5px;">
47                <a href="javascript:switchViewTo('table_view');">Normal View</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""
48
49        poll_info_div = ""
50        if self.status == "complete":
51            resp += """<a href="javascript:switchViewTo('xml_view');">View as XML</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
52                <a href="javascript:switchViewTo('plots_view');">View Plots (if available)</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"""
53        elif self.status == "running":
54            poll_info_div = '<div id="poll_info" class="poller"></div>'
55
56        resp  += """
57</div>
58<div id="view_container" style="background: white; border: 2px outset blue; padding: 5px;">
59        <div id="view_contents">
60                <div id="table_view" style="visibility: visible; height: auto;">%s%s</div>""" % (poll_info_div, job_as_table)
61
62        if self.status == "complete":
63            resp += """
64                <div id="xml_view" style="visibility: hidden; height: 0px;">%s</div>
65                <div id="plots_view" style="visibility: hidden; height: 0px;">%s</div>
66</div>""" % (job_xml_encoded, job_as_plots)
67
68        elif self.status == "running":
69            jobviewer_url = url_for(controller='jobviewer', status_url = status_url)
70            base_url = "http://" + request.url[7:].split("/")[0]
71            full_url = base_url + jobviewer_url
72
73            resp += """<input type="hidden" id="poll_url" value="%s" />""" % status_url
74            resp += """<input type="hidden" id="jobviewer_url" value="%s" />""" % jobviewer_url
75            resp += """<script type="text/javascript">
76        function init() {
77                pollWPS();
78        }
79
80</script>"""
81
82        renderer = UIPageRenderer()
83        resp = renderer.render("WPS Job Information",
84                              [("Job: %s" % self.job_id, resp)])
85        return resp
86
87    def _resolveStatus(self, status_node):
88        snode = status_node.getchildren()[0].tag
89        mdict = {"Succeeded": "complete",
90                 "Failed": "failed",
91                 "Accepted": "running",
92                 "Started": "running"}
93
94        for k,v in mdict.items():
95            if snode.find(k) > -1:
96                return v
97        else:
98            raise Exception("Could not match status tag.")
99
100    def _xmlToTable(self, xml):
101        "Chops up xml to get table of outputs."
102        self.node = ET.fromstring(xml)
103        self.namespace_ows = "http://www.opengeospatial.net/ows"
104        self.namespace = "http://www.opengeospatial.net/wps"
105
106        self.status = self._resolveStatus(self.node.find("{" + self.namespace + "}Status")) 
107
108        job_details = self.node.find("{" + self.namespace +  "}ProcessOutputs").find("{" + self.namespace +  "}Output").find("{" + self.namespace +  "}ComplexValue").find("{" + self.namespace +  "}WPSResponseDetails").find("{" + self.namespace +  "}JobDetails")
109
110        file_set_list = job_details.find("{" + self.namespace +  "}FileSet").getchildren()
111
112        items = ["JobID", "JobCompletionTimeDate", "RequestDescription",
113                 "RequestType", "JobDuration", "JobVolume"]
114        mapped_names = ["Job ID", "Completion Time", 
115                        "Request Description", "Request Type"]
116
117        if self.status == "complete":
118            mapped_names.extend(["Job Duration (seconds)", "Output Size (bytes)"])
119        else:
120            mapped_names.extend(["Estimated Job Duration (seconds)", "Estimated Output Size (bytes)"])
121
122        resp = "<h2>DETAILS</h2>"
123        resp += "Need to realise that in costonly response we have JobCompletionTimeDate empty because it hasn't run yet!<br><br>"
124
125        self.job_id = job_details.find("{" + self.namespace + "}JobID").text
126
127        for (i, item) in enumerate(items):
128            x = job_details.find("{" + self.namespace +  "}" + item).text
129            if type(x) != str: x = "Undefined"
130            resp += "<b>%s</b> = %s<br>" % (mapped_names[i], x.strip())
131
132        file_items = ["FileSize"]
133        mapped_file_items = ["File Size (Bytes)"]
134
135        if self.status == "complete":
136
137            resp += "<h2>OUTPUTS</h2>The following file outputs are available from your job.<br>"
138            for fnode in file_set_list:
139
140                furl = fnode.find("{" + self.namespace +  "}FileURL").text
141                fname = furl.split("/")[-1]
142                len_fname = len(fname)
143
144                p = 70
145                padding = p - len_fname
146                if padding < 0: padding = 0
147
148                resp += ('<br><kbd>%s [<a href="%s">Download</a>]</kbd>' + (padding * "&nbsp;")) % (fname, furl)
149
150                for (i, file_item) in enumerate(file_items):
151                    x = fnode.find("{" + self.namespace +  "}" + file_item).text
152                    resp += '%s Bytes' % x
153
154        return resp
155
156
157    def _htmlifyXML(self, xml):
158        "Returns html string that will make XML look ok on HTML page."
159        xml1 = xml.replace("<", "&lt;").replace(">", "&gt;").replace("\n", "<br>")
160
161        def retag(x): return x.replace("<", "&lt;").replace(">", "&gt;")
162
163        open_and_close = re.compile("^<([^/]+?)>.*?</\1>$")
164        open = re.compile("^<([^/]+)>$")
165        close = re.compile("^</(.+?)>$")
166        empty = re.compile("^<(.+?)/>$")
167        bad = re.compile("^</(.+?)>\s*<([^/]+)>$")
168
169        lines = [i.strip() for i in xml.split("\n")]
170
171        spant = '%s<span style="color: #%s;">%s</span><br>'
172        x = ""
173        pad = 0
174        pc = "&nbsp;" * 4
175
176        for line in lines:
177
178            colour = pad * 50000 
179            col = ("000000" + hex(colour).split("x")[-1])[-6:]
180            line2 = retag(line)
181
182            open_and_close_m = open_and_close.match(line)
183            open_m = open.match(line) 
184            close_m = close.match(line)
185            empty_m = empty.match(line)
186            bad_m = bad.match(line)
187
188            if line == lines[0]:
189                line = spant % (pc * pad, "0000ff", line2)
190                pad += 1
191            elif bad_m:
192                (first, second) = bad_m.groups()[:2]
193                pad -= 1
194                line1 = spant % (pc * pad, "%s" % col, "&lt;/%s&gt;" % first)
195                line2 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % second)
196                line = line1 + line2
197                pad += 1
198            elif open_m:
199                line = spant % (pc * pad, "%s" % col, line2) 
200                pad += 1
201            elif close_m:
202                pad -= 1
203                line = spant % (pc * pad, "%s" % col, line2)
204            elif open_and_close_m:
205                line = spant % (pc * pad, "%s" % col, line2)
206            elif empty_m:
207                line = spant % (pc * pad, "%s" % col, line2)
208            else:
209                line = spant % (pc * pad, "0000ff", line2)
210
211            x += line
212
213        return x
214
215
Note: See TracBrowser for help on using the repository browser.