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

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

changes

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: 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.