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