1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/examples/BaseHTTPRequestHandler/ConfiguratorApp.py Thu Dec 30 02:03:35 2004 +0000
1.3 @@ -0,0 +1,15 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +from WebStack.Adapters import BaseHTTPRequestHandler
1.7 +from Configurator import ConfiguratorResource
1.8 +import BaseHTTPServer
1.9 +
1.10 +# Special magic incantation.
1.11 +
1.12 +handler = BaseHTTPRequestHandler.HandlerFactory(ConfiguratorResource())
1.13 +address = ("", 8080)
1.14 +server = BaseHTTPServer.HTTPServer(address, handler)
1.15 +print "Serving..."
1.16 +server.serve_forever()
1.17 +
1.18 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/examples/Common/Configurator/Resources/config_database.xml Thu Dec 30 02:03:35 2004 +0000
2.3 @@ -0,0 +1,38 @@
2.4 +<?xml version="1.0"?>
2.5 +<database>
2.6 + <base-system>
2.7 + <base-system-enum value="(Not selected)" price="0"/>
2.8 + <base-system-enum value="Shuttle SB61G2V3" price="2174"/>
2.9 + <base-system-enum value="Shuttle SB65G2" price="2700"/>
2.10 + </base-system>
2.11 + <cpu>
2.12 + <cpu-enum value="(Not selected)" price="0"/>
2.13 + <cpu-enum value="Pentium 4 3.0 GHz" price="1650"/>
2.14 + <cpu-enum value="Athlon 3000+" price="1500"/>
2.15 + </cpu>
2.16 + <memory-unit>
2.17 + <memory-unit-enum value="(Not selected)" price="0"/>
2.18 + <memory-unit-enum value="PC3200 DDR RAM 256MB" price="500"/>
2.19 + <memory-unit-enum value="PC3200 DDR RAM 512MB" price="800"/>
2.20 + </memory-unit>
2.21 + <storage-unit>
2.22 + <storage-unit-enum value="(Not selected)" price="0"/>
2.23 + <storage-unit-enum value="CD-ROM 48x" price="200"/>
2.24 + <storage-unit-enum value="CD-RW 48x/24x/48x" price="400"/>
2.25 + <storage-unit-enum value="DVD+-RW 8x" price="750"/>
2.26 + </storage-unit>
2.27 + <hard-disk>
2.28 + <hard-disk-enum value="(Not selected)" price="0"/>
2.29 + <hard-disk-enum value="ATA-133 80GB" price="600"/>
2.30 + <hard-disk-enum value="ATA-133 160GB" price="1000"/>
2.31 + </hard-disk>
2.32 + <keyboard>
2.33 + <keyboard-enum value="(Not selected)" price="0"/>
2.34 + </keyboard>
2.35 + <mouse>
2.36 + <mouse-enum value="(Not selected)" price="0"/>
2.37 + </mouse>
2.38 + <screen>
2.39 + <screen-enum value="(Not selected)" price="0"/>
2.40 + </screen>
2.41 +</database>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/examples/Common/Configurator/Resources/config_database.xsl Thu Dec 30 02:03:35 2004 +0000
3.3 @@ -0,0 +1,104 @@
3.4 +<?xml version="1.0" encoding="utf-8"?>
3.5 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3.6 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"
3.7 + version="1.0">
3.8 +
3.9 + <xsl:param name="database"/>
3.10 +
3.11 + <xsl:template match="configuration">
3.12 + <xsl:copy>
3.13 + <xsl:apply-templates select="@*"/>
3.14 + <!-- Complete all multiple choice fields. -->
3.15 + <details>
3.16 + <xsl:call-template name="complete-element">
3.17 + <xsl:with-param name="found-elements" select="details/base-system"/>
3.18 + <xsl:with-param name="element-name">base-system</xsl:with-param>
3.19 + </xsl:call-template>
3.20 + <xsl:call-template name="complete-element">
3.21 + <xsl:with-param name="found-elements" select="details/cpu"/>
3.22 + <xsl:with-param name="element-name">cpu</xsl:with-param>
3.23 + </xsl:call-template>
3.24 + </details>
3.25 + <memory>
3.26 + <xsl:for-each select="memory/memory-unit">
3.27 + <xsl:call-template name="complete-element">
3.28 + <xsl:with-param name="found-elements" select="."/>
3.29 + <xsl:with-param name="element-name">memory-unit</xsl:with-param>
3.30 + </xsl:call-template>
3.31 + </xsl:for-each>
3.32 + </memory>
3.33 + <hard-disks>
3.34 + <xsl:for-each select="hard-disks/hard-disk">
3.35 + <xsl:call-template name="complete-element">
3.36 + <xsl:with-param name="found-elements" select="."/>
3.37 + <xsl:with-param name="element-name">hard-disk</xsl:with-param>
3.38 + </xsl:call-template>
3.39 + </xsl:for-each>
3.40 + </hard-disks>
3.41 + <storage>
3.42 + <xsl:for-each select="storage/storage-unit">
3.43 + <xsl:call-template name="complete-element">
3.44 + <xsl:with-param name="found-elements" select="."/>
3.45 + <xsl:with-param name="element-name">storage-unit</xsl:with-param>
3.46 + </xsl:call-template>
3.47 + </xsl:for-each>
3.48 + </storage>
3.49 + <peripherals>
3.50 + <xsl:call-template name="complete-element">
3.51 + <xsl:with-param name="found-elements" select="peripherals/keyboard"/>
3.52 + <xsl:with-param name="element-name">keyboard</xsl:with-param>
3.53 + </xsl:call-template>
3.54 + <xsl:call-template name="complete-element">
3.55 + <xsl:with-param name="found-elements" select="peripherals/mouse"/>
3.56 + <xsl:with-param name="element-name">mouse</xsl:with-param>
3.57 + </xsl:call-template>
3.58 + <xsl:call-template name="complete-element">
3.59 + <xsl:with-param name="found-elements" select="peripherals/screen"/>
3.60 + <xsl:with-param name="element-name">screen</xsl:with-param>
3.61 + </xsl:call-template>
3.62 + </peripherals>
3.63 + </xsl:copy>
3.64 + </xsl:template>
3.65 +
3.66 + <xsl:template name="complete-element">
3.67 + <xsl:param name="found-elements"/>
3.68 + <xsl:param name="element-name"/>
3.69 + <xsl:variable name="element-enum-name"><xsl:value-of select="$element-name"/>-enum</xsl:variable>
3.70 + <xsl:variable name="has-set-values" select="$found-elements[@value]"/>
3.71 + <!-- Make the element with the different values. -->
3.72 + <xsl:element name="{$element-name}">
3.73 + <!-- Find the values in the database. -->
3.74 + <xsl:for-each select="$database/database/*[local-name() = $element-name]/*[local-name() = $element-enum-name]">
3.75 + <xsl:variable name="enum-element" select="."/>
3.76 + <!-- Copy each option. -->
3.77 + <xsl:copy>
3.78 + <!-- Only include the value, adding the price only if the item is selected. -->
3.79 + <xsl:apply-templates select="@value"/>
3.80 + <!-- Find whether this item is selected. -->
3.81 + <xsl:choose>
3.82 + <!-- In the current field, the value attribute matches this value. -->
3.83 + <xsl:when test="$found-elements[@value = $enum-element/@value]">
3.84 + <xsl:attribute name="value-is-set">true</xsl:attribute>
3.85 + <xsl:apply-templates select="@price"/>
3.86 + </xsl:when>
3.87 + <!-- This value is the first and no value attribute is specified. -->
3.88 + <xsl:when test="not($has-set-values) and count($enum-element/preceding-sibling::*) = 0">
3.89 + <xsl:attribute name="value-is-set">true</xsl:attribute>
3.90 + <xsl:apply-templates select="@price"/>
3.91 + </xsl:when>
3.92 + <xsl:otherwise/>
3.93 + </xsl:choose>
3.94 + </xsl:copy>
3.95 + </xsl:for-each>
3.96 + </xsl:element>
3.97 + </xsl:template>
3.98 +
3.99 + <!-- Replicate unknown elements. -->
3.100 +
3.101 + <xsl:template match="@*|node()">
3.102 + <xsl:copy>
3.103 + <xsl:apply-templates select="@*|node()"/>
3.104 + </xsl:copy>
3.105 + </xsl:template>
3.106 +
3.107 +</xsl:stylesheet>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/examples/Common/Configurator/Resources/config_input.xml Thu Dec 30 02:03:35 2004 +0000
4.3 @@ -0,0 +1,11 @@
4.4 +<?xml version="1.0"?>
4.5 +<configuration>
4.6 + <details>
4.7 + <base-system value="Shuttle SB65G2"/>
4.8 + <cpu value="Pentium 4 3.0 GHz"/>
4.9 + </details>
4.10 + <memory>
4.11 + <memory-unit value="PC3200 DDR RAM 512MB"/>
4.12 + <memory-unit value="PC3200 DDR RAM 256MB"/>
4.13 + </memory>
4.14 +</configuration>
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/examples/Common/Configurator/Resources/config_template.xhtml Thu Dec 30 02:03:35 2004 +0000
5.3 @@ -0,0 +1,131 @@
5.4 +<?xml version="1.0" encoding="iso-8859-1"?>
5.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
5.6 + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
5.7 +<html xmlns="http://www.w3.org/1999/xhtml"
5.8 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template">
5.9 +<head>
5.10 + <title>System Configurator</title>
5.11 + <meta name="generator" content="amaya 8.1a, see http://www.w3.org/Amaya/" />
5.12 + <link xmlns:xlink="http://www.w3.org/1999/xlink" href="styles.css"
5.13 + rel="stylesheet" type="text/css" />
5.14 +</head>
5.15 +
5.16 +<body>
5.17 +<h1>System Configurator</h1>
5.18 +
5.19 +<form method="post" action="" template:element="configuration">
5.20 +<div id="left">
5.21 + <div template:element="details" class="details">
5.22 + <h2>Base System</h2>
5.23 +
5.24 + <p template:element="base-system">Model
5.25 + <select name="{template:multi-field-name('value')}">
5.26 + <option template:element="base-system-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.27 + value="{@value}"></option>
5.28 + </select>
5.29 + </p>
5.30 +
5.31 + <h2>Processor</h2>
5.32 +
5.33 + <p template:element="cpu">CPU
5.34 + <select name="{template:multi-field-name('value')}">
5.35 + <option template:element="cpu-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.36 + value="{@value}"></option>
5.37 + </select>
5.38 + </p>
5.39 + </div>
5.40 +
5.41 + <div template:element="memory" class="memory">
5.42 + <h2>Memory</h2>
5.43 +
5.44 + <p template:element="memory-unit">Memory unit
5.45 + <select name="{template:multi-field-name('value')}">
5.46 + <option template:element="memory-unit-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.47 + value="{@value}"></option>
5.48 + </select>
5.49 +
5.50 + <input type="submit" value="Remove"
5.51 + name="remove-memory-unit={template:this-position()}" /></p>
5.52 +
5.53 + <p>
5.54 + <input type="submit" value="Add memory"
5.55 + name="add-memory-unit={template:this-position()}" /></p>
5.56 + </div>
5.57 +</div>
5.58 +<div id="right">
5.59 + <div template:element="hard-disks" class="hard-disks">
5.60 + <h2>Hard Disks</h2>
5.61 +
5.62 + <p template:element="hard-disk">Hard disk drive
5.63 + <select name="{template:multi-field-name('value')}">
5.64 + <option template:element="hard-disk-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.65 + value="{@value}"></option>
5.66 + </select>
5.67 +
5.68 + <input type="submit" value="Remove"
5.69 + name="remove-hard-disk={template:this-position()}" /></p>
5.70 +
5.71 + <p>
5.72 + <input type="submit" value="Add hard disk"
5.73 + name="add-hard-disk={template:this-position()}" /></p>
5.74 + </div>
5.75 +
5.76 + <div template:element="storage" class="storage">
5.77 + <h2>Additional Storage</h2>
5.78 +
5.79 + <p template:element="storage-unit">Storage unit
5.80 + <select name="{template:multi-field-name('value')}">
5.81 + <option template:element="storage-unit-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.82 + value="{@value}"></option>
5.83 + </select>
5.84 +
5.85 + <input type="submit" value="Remove"
5.86 + name="remove-storage-unit={template:this-position()}" /></p>
5.87 +
5.88 + <p>
5.89 + <input type="submit" value="Add storage"
5.90 + name="add-storage-unit={template:this-position()}" /></p>
5.91 + </div>
5.92 +</div>
5.93 +<div id="bottom">
5.94 + <div template:element="peripherals" class="peripherals">
5.95 + <h2>Input Devices</h2>
5.96 +
5.97 + <p template:element="keyboard">Keyboard
5.98 + <select name="{template:multi-field-name('value')}">
5.99 + <option template:element="keyboard-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.100 + value="{@value}"></option>
5.101 + </select>
5.102 + </p>
5.103 +
5.104 + <p template:element="mouse">Mouse
5.105 + <select name="{template:multi-field-name('value')}">
5.106 + <option template:element="mouse-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.107 + value="{@value}"></option>
5.108 + </select>
5.109 + </p>
5.110 +
5.111 + <h2>Display</h2>
5.112 +
5.113 + <p template:element="screen">Screen
5.114 + <select name="{template:multi-field-name('value')}">
5.115 + <option template:element="screen-enum" template:expr="@value-is-set" template:expr-attr="selected" template:value="@value"
5.116 + value="{@value}"></option>
5.117 + </select>
5.118 + </p>
5.119 + </div>
5.120 +
5.121 + <div class="price">
5.122 + <h2>Price</h2>
5.123 +
5.124 + <p>Total for this configuration:
5.125 + <span template:value="sum(/configuration//*/@price)"></span></p>
5.126 +
5.127 + <p>
5.128 + <input type="submit" value="Update!" name="update" />
5.129 + <input type="submit" value="Export!" name="export" /></p>
5.130 + </div>
5.131 +</div>
5.132 +</form>
5.133 +</body>
5.134 +</html>
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/examples/Common/Configurator/__init__.py Thu Dec 30 02:03:35 2004 +0000
7.3 @@ -0,0 +1,129 @@
7.4 +#!/usr/bin/env python
7.5 +
7.6 +"A WebStack application for a system configurator."
7.7 +
7.8 +import WebStack.Generic
7.9 +import XSLForms.Fields
7.10 +import XSLForms.Output
7.11 +import XSLOutput
7.12 +import libxml2dom
7.13 +import os
7.14 +
7.15 +# NOTE: Move these functions into a common utility library.
7.16 +
7.17 +def add_elements(positions, element_name, element_parent_name=None):
7.18 + if not positions:
7.19 + return
7.20 + for position in positions:
7.21 + if element_parent_name:
7.22 + parent_elements = position.xpath(element_parent_name)
7.23 + if not parent_elements:
7.24 + parent_element = position.ownerDocument.createElementNS(None, element_parent_name)
7.25 + position.appendChild(parent_element)
7.26 + else:
7.27 + parent_element = parent_elements[0]
7.28 + else:
7.29 + parent_element = position
7.30 + parent_element.appendChild(position.ownerDocument.createElementNS(None, element_name))
7.31 +
7.32 +def remove_elements(positions):
7.33 + if not positions:
7.34 + return
7.35 + for position in positions:
7.36 + position.parentNode.removeChild(position)
7.37 +
7.38 +class ConfiguratorResource:
7.39 +
7.40 + "A resource providing a system configurator."
7.41 +
7.42 + resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
7.43 + encoding = "utf-8"
7.44 +
7.45 + def respond(self, trans):
7.46 +
7.47 + # Produce stylesheet.
7.48 +
7.49 + if trans.get_path_info().split("/")[-1] == "styles.css":
7.50 + trans.set_content_type(WebStack.Generic.ContentType("text/css", self.encoding))
7.51 + out = trans.get_response_stream()
7.52 + f = open(os.path.join(self.resource_dir, "styles.css"), "rb")
7.53 + out.write(f.read())
7.54 + f.close()
7.55 + raise WebStack.Generic.EndOfResponse
7.56 +
7.57 + global XSLForms # NOTE: Strangely required to avoid UnboundLocalError!
7.58 + method = trans.get_request_method()
7.59 +
7.60 + # Only obtain field information according to the stated method.
7.61 +
7.62 + if method == "GET":
7.63 + fields = XSLForms.Fields.Fields(encoding="iso-8859-1", values_are_lists=1)
7.64 + parameters = trans.get_fields_from_path()
7.65 + documents = fields.make_documents(parameters.items())
7.66 + elif method == "POST":
7.67 + fields = XSLForms.Fields.Fields(encoding=self.encoding, values_are_lists=1)
7.68 + parameters = trans.get_fields_from_body(self.encoding)
7.69 + documents = fields.make_documents(parameters.items())
7.70 + else:
7.71 + trans.set_response_code(405)
7.72 + raise WebStack.Generic.EndOfResponse
7.73 +
7.74 + # Ensure the presence of a document.
7.75 +
7.76 + if documents.has_key("configuration"):
7.77 + configuration = documents["configuration"]
7.78 + else:
7.79 + configuration = fields.new_instance("configuration")
7.80 +
7.81 + # Add and remove elements according to the selectors found.
7.82 +
7.83 + selectors = fields.get_selectors(parameters.items(), documents)
7.84 + add_elements(selectors.get("add-memory-unit"), "memory-unit")
7.85 + remove_elements(selectors.get("remove-memory-unit"))
7.86 + add_elements(selectors.get("add-storage-unit"), "storage-unit")
7.87 + remove_elements(selectors.get("remove-storage-unit"))
7.88 + add_elements(selectors.get("add-hard-disk"), "hard-disk")
7.89 + remove_elements(selectors.get("remove-hard-disk"))
7.90 +
7.91 + # Send a response according to certain parameters.
7.92 + # When exported, an XML version of the data is returned.
7.93 +
7.94 + if parameters.has_key("export"):
7.95 + trans.set_content_type(WebStack.Generic.ContentType("text/xml", self.encoding))
7.96 + libxml2dom.toStream(configuration, trans.get_response_stream(), trans.get_response_stream_encoding())
7.97 +
7.98 + # When not exported, the data is transformed to produce a normal Web
7.99 + # page.
7.100 +
7.101 + else:
7.102 +
7.103 + # Transform, adding enumerations/ranges.
7.104 +
7.105 + database_xsl = os.path.join(self.resource_dir, "config_database.xsl")
7.106 + database_xml = os.path.join(self.resource_dir, "config_database.xml")
7.107 + proc = XSLOutput.Processor([database_xsl], {"database" : database_xml})
7.108 + configuration = proc.get_result(configuration)
7.109 +
7.110 + # Start the response.
7.111 +
7.112 + trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding))
7.113 +
7.114 + # Ensure that an output stylesheet exists.
7.115 +
7.116 + trans_xsl = os.path.join(self.resource_dir, "config_output.xsl")
7.117 + template_xml = os.path.join(self.resource_dir, "config_template.xhtml")
7.118 +
7.119 + if not os.path.exists(trans_xsl) or \
7.120 + os.path.getmtime(trans_xsl) < os.path.getmtime(template_xml):
7.121 +
7.122 + import XSLForms.Prepare
7.123 + template_xml = os.path.join(self.resource_dir, "config_template.xhtml")
7.124 + XSLForms.Prepare.make_stylesheet(template_xml, trans_xsl)
7.125 +
7.126 + # Complete the response.
7.127 +
7.128 + proc = XSLOutput.Processor([trans_xsl])
7.129 + proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(),
7.130 + configuration)
7.131 +
7.132 +# vim: tabstop=4 expandtab shiftwidth=4