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

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

various fixes on bbox etc

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", "JobCapabilities", "JobDuration", "JobVolume"]
113        mapped_names = ["Job ID", "Completion Time", 
114                        "Request Description", "Request Type", "Job Capabilities"]
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: 
128                x = "Undefined"
129
130            x = x.strip()
131            if item == "JobCapabilities" and x.find("send_to_extract_weather_data") > -1:
132                x = x.replace("send_to_extract_weather_data", 
133                  '<a href="/submit/form?proc_id=ExtractUKStationData&StationsFile=%s">Use stations to extract UK weather data</a>' % file_set_list[0].find("{" + self.namespace +  "}FileURL").text)
134 
135            resp += "<b>%s</b> = %s<br>" % (mapped_names[i], x.strip())
136
137        file_items = ["FileSize"]
138        mapped_file_items = ["File Size (Bytes)"]
139
140        if self.status == "complete":
141
142            resp += "<h2>OUTPUT FILES</h2>"
143
144            if len(file_set_list) > 0:
145                resp += "The following file outputs are available from your job.<br>"
146            else:
147                resp += 'There are no output files associated with your job. Please click the "View as XML" link above to view your output.<br>'
148
149            for fnode in file_set_list:
150
151                furl = fnode.find("{" + self.namespace +  "}FileURL").text
152                fname = furl.split("/")[-1]
153                len_fname = len(fname)
154
155                p = 70
156                padding = p - len_fname
157                if padding < 0: padding = 0
158
159                resp += ('<br><kbd>%s [<a href="%s">Download</a>]</kbd>' + (padding * "&nbsp;")) % (fname, furl)
160
161                for (i, file_item) in enumerate(file_items):
162                    x = fnode.find("{" + self.namespace +  "}" + file_item).text
163                    resp += '%s Bytes' % x
164
165        return resp
166
167
168    def _htmlifyXML(self, xml):
169        "Returns html string that will make XML look ok on HTML page."
170        xml1 = xml.replace("<", "&lt;").replace(">", "&gt;").replace("\n", "<br>")
171
172        def retag(x): return x.replace("<", "&lt;").replace(">", "&gt;")
173
174        open_and_close = re.compile("^<([^/]+?)>.*?</\1>$")
175        open = re.compile("^<([^/]+)>$")
176        close = re.compile("^</(.+?)>$")
177        empty = re.compile("^<(.+?)/>$")
178        bad = re.compile("^</(.+?)>\s*<([^/]+)>$")
179
180        lines = [i.strip() for i in xml.split("\n")]
181
182        spant = '%s<span style="color: #%s;">%s</span><br>'
183        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>'
184
185        x = ""
186        pad = 0
187        pc = "&nbsp;" * 4
188
189        for line in lines:
190
191            colour = pad * 50000 
192            col = ("000000" + hex(colour).split("x")[-1])[-6:]
193            line2 = retag(line)
194
195            open_and_close_m = open_and_close.match(line)
196            open_m = open.match(line) 
197            close_m = close.match(line)
198            empty_m = empty.match(line)
199            bad_m = bad.match(line)
200
201            if line == lines[0]:
202                line = spant % (pc * pad, "0000ff", line2)
203                pad += 1
204            elif open_and_close_m:
205                groups = open_and_close_m.groups()
206                (tag, content) = groups[:2]
207                line = span2 % (pc * pad, "%s" % col, tag, "000000", content, "%s" * col, tag)
208#                line = spant % (pc * pad, "%s" % col, line2)
209            elif bad_m:
210                (first, second) = bad_m.groups()[:2]
211                pad -= 1
212                line1 = spant % (pc * pad, "%s" % col, "&lt;/%s&gt;" % first)
213                line2 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % second)
214                line = line1 + line2
215                pad += 1
216            elif open_m:
217                line = spant % (pc * pad, "%s" % col, line2) 
218                pad += 1
219            elif close_m:
220                pad -= 1
221                line = spant % (pc * pad, "%s" % col, line2)
222            elif empty_m:
223                line = spant % (pc * pad, "%s" % col, line2)
224            else:
225                line = spant % (pc * pad, "0000ff", line2)
226
227            x += line
228
229        return x
230
231
Note: See TracBrowser for help on using the repository browser.