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

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

lots of minor fixes. including removing username from process configs.

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