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, 10 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.