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

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

job viewer has strange reload behaviour if you scroll down!

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.utils.common import *
19from cows_wps.renderer.ui_renderer import *
20from cows_wps.model.managers import requestManager
21from cows_wps.process_handler.context.process_context import ProcessContext
22from cows_wps.renderer import xml_renderer
23
24from cows_wps.utils.parse_wps_config import wps_config_dict
25from cows_wps.utils.parse_capabilities_config import caps_config_dict
26
27
28from cows_wps.model.managers import requestManager
29
30log = logging.getLogger(__name__)
31
32
33class JobviewerController(BaseController):
34
35
36    def index(self):
37        status_url = str(request.params.getone("status_url"))
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", "JobCapabilities", "JobDuration", "JobVolume"]
114        mapped_names = ["Job ID", "Completion Time", 
115                        "Request Description", "Request Type", "Job Capabilities"]
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
124        self.job_id = job_details.find("{" + self.namespace + "}JobID").text
125
126        for (i, item) in enumerate(items):
127            x = job_details.find("{" + self.namespace +  "}" + item).text
128            if type(x) != str: 
129                x = "Undefined"
130
131            x = x.strip()
132            if item == "JobCapabilities" and x.find("send_to_extract_weather_data") > -1:
133                file_url = file_set_list[0].find("{" + self.namespace +  "}FileURL").text
134#                x = x.replace("send_to_extract_weather_data",
135#                  '<a href="/submit/form?proc_id=ExtractUKStationData&StationsFile=%s">Use stations to extract UK weather data</a>' % file_url)
136                file_path = mapDownloadURLToFilePath(file_url)
137                x = x.replace("send_to_extract_weather_data",
138                  '<a href="/submit/form?proc_id=ExtractUKStationData&StationsFile=%s">Use stations to extract UK weather data</a>' % file_path) 
139 
140            resp += "<b>%s</b> = %s<br>" % (mapped_names[i], x.strip())
141
142        file_items = ["FileSize"]
143        mapped_file_items = ["File Size (Bytes)"]
144
145        if self.status == "complete":
146
147            resp += "<h2>OUTPUT FILES</h2>"
148
149            if len(file_set_list) > 0:
150                resp += "The following file outputs are available from your job.<br>"
151            else:
152                resp += 'There are no output files associated with your job. Please click the "View as XML" link above to view your output.<br>'
153
154            for fnode in file_set_list:
155
156                furl = fnode.find("{" + self.namespace +  "}FileURL").text
157                fname = furl.split("/")[-1]
158                len_fname = len(fname)
159
160                p = 70
161                padding = p - len_fname
162                if padding < 0: padding = 0
163
164                resp += ('<br><kbd>%s [<a href="%s">Download</a>]</kbd>' + (padding * "&nbsp;")) % (fname, furl)
165
166                for (i, file_item) in enumerate(file_items):
167                    x = fnode.find("{" + self.namespace +  "}" + file_item).text
168                    resp += '%s Bytes' % x
169
170        return resp
171
172
173    def _htmlifyXML(self, xml):
174        "Returns html string that will make XML look ok on HTML page."
175        xml1 = xml.replace("<", "&lt;").replace(">", "&gt;").replace("\n", "<br>")
176
177        def retag(x): return x.replace("<", "&lt;").replace(">", "&gt;")
178
179        open_and_close = re.compile(r"^<([^/]+?)>(.*?)</\1>$")
180        open_and_open = re.compile(r"^<([^/]+?)>\s*<([^/]+?)>$")
181        close_and_close = re.compile(r"^<(/.+?)>\s*<(/.+?)>$")
182        open = re.compile(r"^<([^/]+)>$")
183        close = re.compile(r"^</(.+?)>$")
184        empty = re.compile(r"^<(.+?)/>$")
185        bad = re.compile(r"^</(.+?)>\s*<([^/]+)>$")
186
187        lines = [i.strip() for i in xml.split("\n")]
188
189        spant = '%s<span style="color: #%s;">%s</span><br>'
190        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>'
191
192        x = ""
193        pad = 0
194        pc = "&nbsp;" * 4
195
196        for line in lines:
197
198            colour = pad * 50000 
199            col = ("000000" + hex(colour).split("x")[-1])[-6:]
200            line2 = retag(line)
201
202            open_and_close_m = open_and_close.match(line)
203            open_and_open_m = False#open_and_open.match(line)
204            close_and_close_m = False#close_and_close.match(line)
205            open_m = open.match(line) 
206            close_m = close.match(line)
207            empty_m = empty.match(line)
208            bad_m = bad.match(line)
209
210            if line == lines[0]:
211                line = spant % (pc * pad, "0000ff", line2)
212                pad += 1
213            elif open_and_close_m:
214                groups = open_and_close_m.groups()
215                (tag, content) = groups[:2]
216                line = span2 % (pc * pad, "%s" % col, tag, "000000", content, "%s" % col, tag)
217            elif open_and_open_m:
218                groups = open_and_open_m.groups()
219                (tag1, tag2) = groups[:2]
220                pad += 1
221                line1 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % tag1)
222                pad += 1
223                line2 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % tag2)
224                line = line1 + line2
225            elif close_and_close_m:
226                groups = close_and_close_m.groups()
227                (tag1, tag2) = groups[:2]
228                pad -= 1
229                line1 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % tag1)
230                pad -= 1
231                line2 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % tag2)
232                line = line1 + line2
233            elif bad_m:
234                (first, second) = bad_m.groups()[:2]
235                pad -= 1
236                line1 = spant % (pc * pad, "%s" % col, "&lt;/%s&gt;" % first)
237                line2 = spant % (pc * pad, "%s" % col, "&lt;%s&gt;" % second)
238                line = line1 + line2
239                pad += 1
240            elif open_m:
241                line = spant % (pc * pad, "%s" % col, line2) 
242                pad += 1
243            elif close_m:
244                pad -= 1
245                line = spant % (pc * pad, "%s" % col, line2)
246            elif empty_m:
247                line = spant % (pc * pad, "%s" % col, line2)
248            else:
249                line = spant % (pc * pad, "0000ff", line2)
250
251            x += line
252
253        return x
254
255
Note: See TracBrowser for help on using the repository browser.