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