paulb@219 | 1 | #!/usr/bin/env python |
paulb@219 | 2 | |
paulb@219 | 3 | "A dictionary example application." |
paulb@219 | 4 | |
paulb@219 | 5 | import WebStack.Generic |
paulb@353 | 6 | import XSLForms.Resources.WebResources |
paulb@219 | 7 | import XSLForms.Utils |
paulb@219 | 8 | import os |
paulb@219 | 9 | |
paulb@219 | 10 | # Site map imports. |
paulb@219 | 11 | |
paulb@219 | 12 | from WebStack.Resources.ResourceMap import MapResource |
paulb@219 | 13 | from WebStack.Resources.Static import DirectoryResource |
paulb@219 | 14 | |
paulb@219 | 15 | # Resource classes. |
paulb@219 | 16 | |
paulb@353 | 17 | class DictionaryResource(XSLForms.Resources.WebResources.XSLFormsResource): |
paulb@219 | 18 | |
paulb@219 | 19 | "A simple resource providing dictionary lookup." |
paulb@219 | 20 | |
paulb@219 | 21 | resource_dir = os.path.join(os.path.split(__file__)[0], "Resources") |
paulb@219 | 22 | encoding = "utf-8" |
paulb@219 | 23 | template_resources = { |
paulb@219 | 24 | "words" : ("words_template.xhtml", "words_output.xsl") |
paulb@219 | 25 | } |
paulb@219 | 26 | in_page_resources = { |
paulb@220 | 27 | "matches" : ("words_output_entry.xsl", "matches-node"), |
paulb@220 | 28 | #"word" : ("words_output_word.xsl", "word-node") |
paulb@219 | 29 | } |
paulb@219 | 30 | |
paulb@219 | 31 | def __init__(self, dict): |
paulb@219 | 32 | |
paulb@219 | 33 | "Initialise the resource with the given 'dict'." |
paulb@219 | 34 | |
paulb@219 | 35 | self.dict = dict |
paulb@219 | 36 | |
paulb@219 | 37 | def respond_to_form(self, trans, form): |
paulb@219 | 38 | |
paulb@219 | 39 | """ |
paulb@219 | 40 | Respond to a request having the given transaction 'trans' and the given |
paulb@219 | 41 | 'form' information. |
paulb@219 | 42 | """ |
paulb@219 | 43 | |
paulb@219 | 44 | in_page_resource = self.get_in_page_resource(trans) |
paulb@219 | 45 | parameters = form.get_parameters() |
paulb@219 | 46 | documents = form.get_documents() |
paulb@219 | 47 | |
paulb@219 | 48 | # Ensure the presence of a document. |
paulb@219 | 49 | |
paulb@219 | 50 | if documents.has_key("words"): |
paulb@219 | 51 | words = documents["words"] |
paulb@219 | 52 | else: |
paulb@219 | 53 | words = form.new_instance("words") |
paulb@219 | 54 | |
paulb@219 | 55 | # Add and remove elements according to the selectors found. |
paulb@219 | 56 | |
paulb@219 | 57 | selectors = form.get_selectors() |
paulb@219 | 58 | XSLForms.Utils.remove_elements(selectors.get("remove")) |
paulb@219 | 59 | XSLForms.Utils.add_elements(selectors.get("add"), "entry") |
paulb@219 | 60 | |
paulb@219 | 61 | # Ensure all entries have a matches element. |
paulb@219 | 62 | # Ensure all matches elements have at least one choice. |
paulb@219 | 63 | # Copy selected matches to their corresponding text field. |
paulb@219 | 64 | |
paulb@223 | 65 | all_entries = words.xpath("words/entry") |
paulb@223 | 66 | |
paulb@223 | 67 | for entry in all_entries: |
paulb@219 | 68 | matches_list = entry.xpath("matches") |
paulb@219 | 69 | if len(matches_list) == 0: |
paulb@219 | 70 | matches = words.createElement("matches") |
paulb@219 | 71 | entry.appendChild(matches) |
paulb@219 | 72 | else: |
paulb@219 | 73 | matches = matches_list[0] |
paulb@219 | 74 | |
paulb@219 | 75 | if len(entry.xpath("matches/match-enum")) == 0: |
paulb@219 | 76 | match_enum = words.createElement("match-enum") |
paulb@219 | 77 | match_enum.setAttribute("word", "") |
paulb@219 | 78 | matches.appendChild(match_enum) |
paulb@219 | 79 | |
paulb@219 | 80 | # Find requested search locations. |
paulb@219 | 81 | |
paulb@219 | 82 | if selectors.has_key("search"): |
paulb@219 | 83 | entries = selectors["search"] |
paulb@220 | 84 | elif in_page_resource == "matches": |
paulb@223 | 85 | entries = all_entries |
paulb@219 | 86 | else: |
paulb@219 | 87 | entries = [] |
paulb@219 | 88 | |
paulb@219 | 89 | # Transform, adding dictionary information. |
paulb@219 | 90 | |
paulb@219 | 91 | for entry in entries: |
paulb@219 | 92 | word = entry.getAttribute("word") |
paulb@219 | 93 | if word != "": |
paulb@219 | 94 | matches = entry.xpath("matches")[0] |
paulb@219 | 95 | for found_word in self.dict.find(word): |
paulb@219 | 96 | match_enum = words.createElement("match-enum") |
paulb@219 | 97 | match_enum.setAttribute("word", found_word) |
paulb@219 | 98 | matches.appendChild(match_enum) |
paulb@219 | 99 | |
paulb@223 | 100 | # Copy selected values into text fields. |
paulb@223 | 101 | # NOTE: Since libxml2dom does not guarantee node equality for two nodes |
paulb@223 | 102 | # NOTE: referring to the same thing, we cannot just loop over all the |
paulb@223 | 103 | # NOTE: entries and query whether they reside in the search locations. |
paulb@223 | 104 | |
paulb@223 | 105 | for entry in all_entries: |
paulb@223 | 106 | matches = entry.xpath("matches")[0] |
paulb@223 | 107 | if matches.hasAttribute("word"): |
paulb@223 | 108 | word = matches.getAttribute("word") |
paulb@223 | 109 | if word != "" and word.startswith(entry.getAttribute("word")): |
paulb@223 | 110 | entry.setAttribute("word", word) |
paulb@223 | 111 | |
paulb@219 | 112 | # Start the response. |
paulb@219 | 113 | |
paulb@219 | 114 | trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding)) |
paulb@219 | 115 | |
paulb@219 | 116 | # Ensure that an output stylesheet exists. |
paulb@219 | 117 | |
paulb@219 | 118 | if in_page_resource in self.in_page_resources.keys(): |
paulb@219 | 119 | trans_xsl = self.prepare_fragment("words", in_page_resource) |
paulb@296 | 120 | stylesheet_parameters = self.prepare_parameters(parameters) |
paulb@219 | 121 | else: |
paulb@219 | 122 | trans_xsl = self.prepare_output("words") |
paulb@296 | 123 | stylesheet_parameters = {} |
paulb@219 | 124 | |
paulb@219 | 125 | # Complete the response. |
paulb@219 | 126 | |
paulb@219 | 127 | self.send_output(trans, [trans_xsl], words, stylesheet_parameters) |
paulb@219 | 128 | |
paulb@219 | 129 | # Site map initialisation. |
paulb@219 | 130 | |
paulb@219 | 131 | def get_site(dict): |
paulb@219 | 132 | |
paulb@219 | 133 | """ |
paulb@219 | 134 | Return a simple Web site resource using the given 'dict' - a dictionary |
paulb@219 | 135 | employed by the application. |
paulb@219 | 136 | """ |
paulb@219 | 137 | |
paulb@219 | 138 | # Get the main resource and the directory used by the application. |
paulb@219 | 139 | |
paulb@219 | 140 | dictionary_resource = DictionaryResource(dict) |
paulb@219 | 141 | directory = dictionary_resource.resource_dir |
paulb@219 | 142 | |
paulb@219 | 143 | # Make a simple Web site. |
paulb@219 | 144 | |
paulb@219 | 145 | resource = MapResource({ |
paulb@219 | 146 | # Static resources: |
paulb@219 | 147 | "scripts" : DirectoryResource(os.path.join(directory, "scripts"), {"js" : "text/javascript"}), |
paulb@219 | 148 | # Main page and in-page resources: |
paulb@227 | 149 | "" : dictionary_resource, |
paulb@227 | 150 | "matches" : dictionary_resource |
paulb@219 | 151 | }) |
paulb@219 | 152 | |
paulb@219 | 153 | return resource |
paulb@219 | 154 | |
paulb@219 | 155 | # vim: tabstop=4 expandtab shiftwidth=4 |