1 #!/usr/bin/env python 2 3 "A job candidate editing application." 4 5 import WebStack.Generic 6 import XSLForms.Resources.WebResources 7 import XSLForms.Utils 8 import os 9 import libxml2dom 10 11 # Site map imports. 12 13 from WebStack.Resources.ResourceMap import MapResource 14 from WebStack.Resources.Static import DirectoryResource 15 16 # Resource classes. 17 18 class AdminResource(XSLForms.Resources.WebResources.XSLFormsResource): 19 20 "A resource providing administration facilities for job candidate profiles." 21 22 resource_dir = os.path.join(os.path.split(__file__)[0], "Resources") 23 encoding = "utf-8" 24 template_resources = { 25 "admin" : ("admin_template.xhtml", "admin_output.xsl") 26 } 27 init_resources = { 28 "admin" : ("admin_template.xhtml", "admin_input.xsl") 29 } 30 31 def respond_to_form(self, trans, form): 32 33 """ 34 Respond to a request having the given transaction 'trans' and the given 35 'form' information. 36 """ 37 38 parameters = form.get_parameters() 39 documents = form.get_documents() 40 41 # Get the "show" and "edit" resource paths. 42 # NOTE: These should be obtained from the site map. 43 44 parts = trans.get_processed_virtual_path_info(self.path_encoding).split("/") 45 show_path = "/".join(parts[:-1] + ["show"]) 46 edit_path = "/".join(parts[:-1] + ["edit"]) 47 48 # Ensure the presence of a document. 49 50 form_is_new = 0 51 if documents.has_key("admin"): 52 admin = documents["admin"] 53 else: 54 admin = form.new_instance("admin") 55 form_is_new = 1 56 57 # Redirect if one of the CVs is to be shown or edited. 58 59 selectors = form.get_selectors() 60 if selectors.has_key("show"): 61 name = selectors["show"][0].getAttribute("name") 62 self._redirect(trans, show_path + "?name=%s" % name.encode(self.path_encoding)) 63 elif selectors.has_key("edit"): 64 name = selectors["edit"][0].getAttribute("name") 65 self._redirect(trans, edit_path + "?name=%s" % name.encode(self.path_encoding)) 66 67 # Add and remove elements according to the selectors found. 68 69 XSLForms.Utils.remove_elements(selectors.get("remove")) 70 XSLForms.Utils.add_elements(selectors.get("new"), "cv", "cvs") 71 72 # Transform, adding enumerations/ranges. 73 74 init_xsl = self.prepare_initialiser("admin") 75 admin = self.get_result([init_xsl], admin) 76 77 # Synchronise the session with the CVs found. 78 79 cvs = admin.xpath("/admin/cvs")[0] 80 session = trans.get_session() 81 for key in session.keys(): 82 if key.startswith("candidate-"): 83 name = key[len("candidate-"):] 84 # NOTE: Apostrophes not quoted. 85 if not cvs.xpath("cv[@name = '%s']" % name): 86 if form_is_new: 87 cv = admin.createElement("cv") 88 cv.setAttribute("name", name) 89 cvs.appendChild(cv) 90 else: 91 del session[key] 92 93 # Start the response. 94 95 trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) 96 97 # Ensure that an output stylesheet exists. 98 99 trans_xsl = self.prepare_output("admin") 100 stylesheet_parameters = {} 101 102 # Complete the response. 103 104 self.send_output(trans, [trans_xsl], admin, stylesheet_parameters) 105 106 def _redirect(self, trans, path): 107 trans.set_response_code(302) 108 trans.set_header_value("Location", path) 109 raise WebStack.Generic.EndOfResponse 110 111 class DisplayResource(XSLForms.Resources.WebResources.XSLFormsResource): 112 113 "A resource providing editing facilities for a job candidate profile." 114 115 resource_dir = os.path.join(os.path.split(__file__)[0], "Resources") 116 encoding = "utf-8" 117 template_resources = { 118 "candidate_display" : ("candidate_display_template.xhtml", "candidate_display_output.xsl") 119 } 120 init_resources = { 121 "candidate" : ("candidate_template.xhtml", "candidate_input.xsl") 122 } 123 document_resources = { 124 "status" : "candidate_status.xml" 125 } 126 127 def respond_to_form(self, trans, form): 128 129 """ 130 Respond to a request having the given transaction 'trans' and the given 131 'form' information. 132 """ 133 134 parameters = form.get_parameters() 135 documents = form.get_documents() 136 fields = trans.get_fields_from_path() 137 name = fields.get("name", [u"None"])[0] 138 139 # Ensure the presence of a document. 140 141 if documents.has_key("candidate"): 142 candidate = documents["candidate"] 143 else: 144 session = trans.get_session(create=0) 145 if session is None or not session.has_key("candidate-%s" % name.encode("utf-8")): 146 candidate = form.new_instance("candidate") 147 else: 148 candidate = libxml2dom.parseString(session["candidate-%s" % name.encode("utf-8")]) 149 150 # Transform, adding enumerations/ranges. 151 152 init_xsl = self.prepare_initialiser("candidate") 153 status_xml = self.prepare_document("status") 154 candidate = self.get_result([init_xsl], candidate, references={"status" : status_xml}) 155 156 # Start the response. 157 158 trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) 159 160 # Ensure that an output stylesheet exists. 161 # Handle the "show" operation. 162 163 trans_xsl = self.prepare_output("candidate_display") 164 stylesheet_parameters = {} 165 166 # Complete the response. 167 168 self.send_output(trans, [trans_xsl], candidate, stylesheet_parameters) 169 170 class CandidateResource(XSLForms.Resources.WebResources.XSLFormsResource): 171 172 "A resource providing editing facilities for a job candidate profile." 173 174 resource_dir = os.path.join(os.path.split(__file__)[0], "Resources") 175 encoding = "utf-8" 176 template_resources = { 177 "candidate" : ("candidate_template.xhtml", "candidate_output.xsl") 178 } 179 init_resources = { 180 "candidate" : ("candidate_template.xhtml", "candidate_input.xsl") 181 } 182 document_resources = { 183 "status" : "candidate_status.xml" 184 } 185 186 def respond_to_form(self, trans, form): 187 188 """ 189 Respond to a request having the given transaction 'trans' and the given 190 'form' information. 191 """ 192 193 parameters = form.get_parameters() 194 documents = form.get_documents() 195 fields = trans.get_fields_from_path() 196 name = fields.get("name", [u"None"])[0] 197 198 # Get the "show" resource path. 199 # NOTE: This should be obtained from the site map. 200 201 parts = trans.get_processed_virtual_path_info(self.path_encoding).split("/") 202 show_path = "/".join(parts[:-1] + ["show"]) 203 admin_path = "/".join(parts[:-1] + [""]) 204 205 # Ensure the presence of a document. 206 207 if documents.has_key("candidate"): 208 candidate = documents["candidate"] 209 else: 210 session = trans.get_session(create=0) 211 if session is None or not session.has_key("candidate-%s" % name.encode("utf-8")): 212 candidate = form.new_instance("candidate") 213 else: 214 candidate = libxml2dom.parseString(session["candidate-%s" % name.encode("utf-8")]) 215 216 # Add and remove elements according to the selectors found. 217 218 selectors = form.get_selectors() 219 XSLForms.Utils.remove_elements(selectors.get("remove")) 220 XSLForms.Utils.add_elements(selectors.get("add-skill"), "skill", "skills") 221 XSLForms.Utils.add_elements(selectors.get("add-qualification"), "qualification", "qualifications") 222 XSLForms.Utils.add_elements(selectors.get("add-employment"), "employment", "experience") 223 224 # Transform, adding enumerations/ranges. 225 226 init_xsl = self.prepare_initialiser("candidate") 227 status_xml = self.prepare_document("status") 228 candidate = self.get_result([init_xsl], candidate, references={"status" : status_xml}) 229 230 # Redirect if the CV is to be shown. 231 232 if parameters.has_key("show"): 233 234 # Save the candidate information. 235 236 session = trans.get_session() 237 session["candidate-%s" % name.encode("utf-8")] = candidate.toString() 238 self._redirect(trans, show_path + "?name=%s" % name.encode(self.path_encoding)) 239 240 # Redirect if the administration interface is to be used. 241 242 elif parameters.has_key("admin"): 243 244 # Save the candidate information. 245 246 session = trans.get_session() 247 session["candidate-%s" % name.encode("utf-8")] = candidate.toString() 248 self._redirect(trans, admin_path) 249 250 # Start the response. 251 252 trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) 253 254 # Ensure that an output stylesheet exists. 255 256 trans_xsl = self.prepare_output("candidate") 257 stylesheet_parameters = {} 258 259 # Complete the response. 260 261 self.send_output(trans, [trans_xsl], candidate, stylesheet_parameters) 262 263 def _redirect(self, trans, path): 264 trans.set_response_code(302) 265 trans.set_header_value("Location", path) 266 raise WebStack.Generic.EndOfResponse 267 268 # Site map initialisation. 269 270 def get_site(): 271 272 "Return a simple Web site resource." 273 274 # Get the main resource and the directory used by the application. 275 276 candidate_resource = CandidateResource() 277 display_resource = DisplayResource() 278 admin_resource = AdminResource() 279 directory = candidate_resource.resource_dir 280 281 # Make a simple Web site. 282 283 resource = MapResource({ 284 "edit" : candidate_resource, 285 "show" : display_resource, 286 "" : admin_resource 287 }) 288 289 return resource 290 291 # vim: tabstop=4 expandtab shiftwidth=4