bruno 2003/07/15 07:11:03
Modified: src/blocks/woody/java/org/apache/cocoon/woody/datatype DynamicSelectionList.java SelectionListBuilder.java StaticSelectionList.java Log: Use Convertors when building and serializing selection lists. Revision Changes Path 1.2 +131 -9 cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/DynamicSelectionList.java Index: DynamicSelectionList.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/DynamicSelectionList.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- DynamicSelectionList.java 26 Jun 2003 15:33:11 -0000 1.1 +++ DynamicSelectionList.java 15 Jul 2003 14:11:03 -0000 1.2 @@ -59,13 +59,20 @@ import org.apache.cocoon.components.source.SourceUtil; import org.apache.cocoon.xml.AttributesImpl; import org.apache.cocoon.xml.AbstractXMLPipe; +import org.apache.cocoon.xml.dom.DOMBuilder; import org.apache.cocoon.woody.Constants; +import org.apache.cocoon.woody.datatype.convertor.Convertor; +import org.apache.cocoon.woody.datatype.convertor.DefaultFormatCache; +import org.w3c.dom.Element; import java.util.Locale; /** * SelectionList implementation that always reads its content from the source * each time it is requested. + * + * <p>Note: the class [EMAIL PROTECTED] SelectionListBuilder} also interprets the same wd:selection-list XML, so if + * anything changes here to how that XML is interpreted, it also needs to change over there and vice versa. */ public class DynamicSelectionList implements SelectionList { private String src; @@ -107,8 +114,15 @@ */ public class SelectionListHandler extends AbstractXMLPipe { private Object currentValue; + private String currentValueAsString; private boolean hasLabel; private Locale locale; + /** The convertor used to parse the values in the selection list. */ + private Convertor convertor; + private DOMBuilder convertorConfigDOMBuilder; + private int convertorConfigNestingLevel = 0; + private Convertor.FormatCache fromFormatCache = new DefaultFormatCache(); + private Convertor.FormatCache toFormatCache = new DefaultFormatCache(); public SelectionListHandler(Locale locale) { this.locale = locale; @@ -132,25 +146,36 @@ public void startElement(String namespaceURI, String localName, String qName, Attributes attributes) throws SAXException { - if (namespaceURI.equals(Constants.WD_NS)) { + if (convertorConfigNestingLevel > 0) { + convertorConfigNestingLevel++; + convertorConfigDOMBuilder.startElement(namespaceURI, localName, qName, attributes); + } else if (namespaceURI.equals(Constants.WD_NS)) { if (localName.equals("item")) { + if (convertor == null) { + // if no convertor was explicitely configured, use the default one of the datatype + convertor = datatype.getConvertor(); + } hasLabel = false; String unparsedValue = attributes.getValue("value"); if (unparsedValue == null) throw new SAXException("Missing value attribute on " + qName + " element."); - currentValue = datatype.convertFromString(unparsedValue); + currentValue = convertor.convertFromString(unparsedValue, locale, fromFormatCache); if (currentValue == null) throw new SAXException("Could not interpret the following value: \"" + unparsedValue + "\"."); AttributesImpl attrs = new AttributesImpl(); - // currently the duo convertFromString and convertToString here seems meaningless, - // but in the future the formats of input and output could change - attrs.addCDATAAttribute("value", datatype.convertToString(currentValue)); + currentValueAsString = datatype.getConvertor().convertToString(currentValue, locale, toFormatCache); + attrs.addCDATAAttribute("value", currentValueAsString); super.startElement(Constants.WI_NS, localName, Constants.WI_PREFIX_COLON + localName, attrs); } else if (localName.equals("label")) { hasLabel = true; super.startElement(Constants.WI_NS, localName, Constants.WI_PREFIX_COLON + localName, attributes); } else if (localName.equals("selection-list")) { super.startElement(Constants.WI_NS, localName, Constants.WI_PREFIX_COLON + localName, attributes); + } else if (convertor == null && localName.equals("convertor")) { + // record the content of this element in a dom-tree + convertorConfigDOMBuilder = new DOMBuilder(); + convertorConfigDOMBuilder.startElement(namespaceURI, localName, qName, attributes); + convertorConfigNestingLevel++; } else { super.startElement(namespaceURI, localName, qName, attributes); } @@ -163,13 +188,23 @@ public void endElement(String namespaceURI, String localName, String qName) throws SAXException { - if (namespaceURI.equals(Constants.WD_NS)) { + if (convertorConfigNestingLevel > 0) { + convertorConfigNestingLevel--; + convertorConfigDOMBuilder.endElement(namespaceURI, localName, qName); + if (convertorConfigNestingLevel == 0) { + Element convertorElement = convertorConfigDOMBuilder.getDocument().getDocumentElement(); + try { + convertor = datatype.getBuilder().buildConvertor(convertorElement); + } catch (Exception e) { + throw new SAXException("Error building convertor from convertor configuration embedded in selection list XML.", e); + } + } + } else if (namespaceURI.equals(Constants.WD_NS)) { if (localName.equals("item")) { if (!hasLabel) { // make the label now super.startElement(Constants.WI_NS, LABEL_EL, Constants.WI_PREFIX_COLON + LABEL_EL, new AttributesImpl()); - String label = datatype.convertToStringLocalized(currentValue, locale); - super.characters(label.toCharArray(), 0, label.length()); + super.characters(currentValueAsString.toCharArray(), 0, currentValueAsString.length()); super.endElement(Constants.WI_NS, LABEL_EL, Constants.WI_PREFIX_COLON + LABEL_EL); } super.endElement(Constants.WI_NS, localName, Constants.WI_PREFIX_COLON + localName); @@ -184,6 +219,93 @@ super.endElement(namespaceURI, localName, qName); } } - } + public void comment(char ch[], int start, int len) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.comment(ch, start, len); + } else + super.comment(ch, start, len); + } + + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.startPrefixMapping(prefix, uri); + } else + super.startPrefixMapping(prefix, uri); + } + + public void endPrefixMapping(String prefix) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.endPrefixMapping(prefix); + } else + super.endPrefixMapping(prefix); + } + + public void characters(char c[], int start, int len) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.characters(c, start, len); + } else + super.characters(c, start, len); + } + + public void ignorableWhitespace(char c[], int start, int len) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.ignorableWhitespace(c, start, len); + } else + super.ignorableWhitespace(c, start, len); + } + + public void processingInstruction(String target, String data) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.processingInstruction(target, data); + } else + super.processingInstruction(target, data); + } + + public void skippedEntity(String name) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.skippedEntity(name); + } else + super.skippedEntity(name); + } + + public void startEntity(String name) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.startEntity(name); + } else + super.startEntity(name); + } + + public void endEntity(String name) + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.endEntity(name); + } else + super.endEntity(name); + } + + public void startCDATA() + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.startCDATA(); + } else + super.startCDATA(); + } + + public void endCDATA() + throws SAXException { + if (convertorConfigNestingLevel > 0) { + convertorConfigDOMBuilder.endCDATA(); + } else + super.endCDATA(); + } + } } 1.2 +22 -2 cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/SelectionListBuilder.java Index: SelectionListBuilder.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/SelectionListBuilder.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SelectionListBuilder.java 22 Apr 2003 12:04:18 -0000 1.1 +++ SelectionListBuilder.java 15 Jul 2003 14:11:03 -0000 1.2 @@ -54,23 +54,43 @@ import org.w3c.dom.NodeList; import org.w3c.dom.Node; import org.apache.cocoon.woody.Constants; +import org.apache.cocoon.woody.datatype.convertor.Convertor; +import org.apache.cocoon.woody.datatype.convertor.DefaultFormatCache; import org.apache.cocoon.woody.util.DomHelper; +import org.xml.sax.SAXException; + +import java.util.Locale; /** * Builds [EMAIL PROTECTED] SelectionList}s from an XML description. + * + * <p>Note: the class [EMAIL PROTECTED] DynamicSelectionList} also interprets the same wd:selection-list XML, so if + * anything changes here to how that XML is interpreted, it also needs to change over there and vice versa. */ public class SelectionListBuilder { public static SelectionList build(Element selectionListElement, Datatype datatype) throws Exception { StaticSelectionList selectionList = new StaticSelectionList(datatype); + Convertor convertor = null; + Convertor.FormatCache formatCache = new DefaultFormatCache(); NodeList children = selectionListElement.getChildNodes(); for (int i = 0; children.item(i) != null; i++) { Node node = children.item(i); - if (node instanceof Element && Constants.WD_NS.equals(node.getNamespaceURI()) && "item".equals(node.getLocalName())) { + if (convertor == null && node instanceof Element && Constants.WD_NS.equals(node.getNamespaceURI()) && "convertor".equals(node.getLocalName())) { + Element convertorConfigElement = (Element)node; + try { + convertor = datatype.getBuilder().buildConvertor(convertorConfigElement); + } catch (Exception e) { + throw new SAXException("Error building convertor from convertor configuration embedded in selection list XML.", e); + } + } else if (node instanceof Element && Constants.WD_NS.equals(node.getNamespaceURI()) && "item".equals(node.getLocalName())) { + if (convertor == null) { + convertor = datatype.getConvertor(); + } Element element = (Element)node; String stringValue = element.getAttribute("value"); - Object value = datatype.convertFromString(stringValue); + Object value = convertor.convertFromString(stringValue, Locale.US, formatCache); if (value == null) throw new Exception("Could not convert the value \"" + stringValue + "\" to the type " + datatype.getDescriptiveName() + ", defined at " + DomHelper.getLocation(element)); 1.3 +12 -7 cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/StaticSelectionList.java Index: StaticSelectionList.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/datatype/StaticSelectionList.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- StaticSelectionList.java 14 May 2003 11:45:43 -0000 1.2 +++ StaticSelectionList.java 15 Jul 2003 14:11:03 -0000 1.3 @@ -53,6 +53,8 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.cocoon.woody.Constants; +import org.apache.cocoon.woody.datatype.convertor.Convertor; +import org.apache.cocoon.woody.datatype.convertor.DefaultFormatCache; import org.apache.cocoon.components.sax.XMLByteStreamInterpreter; import org.apache.cocoon.xml.AttributesImpl; @@ -64,8 +66,9 @@ /** * An implementation of a SelectionList. Create instances of this class by using * the [EMAIL PROTECTED] SelectionListBuilder}. This implementation is called "Static" because - * the list of items is not retrieved dynamically, but only ones and shared for - * all users of the [EMAIL PROTECTED] Datatype}. + * the items in the list are build once from its source, and then list items are + * cached as part of this object. In contrast, the [EMAIL PROTECTED] DynamicSelectionList} + * will retrieve its content from its source each time it's needed. */ public class StaticSelectionList implements SelectionList { /** The datatype to which this selection list belongs */ @@ -86,11 +89,12 @@ } public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException { + Convertor.FormatCache formatCache = new DefaultFormatCache(); contentHandler.startElement(Constants.WI_NS, SELECTION_LIST_EL, Constants.WI_PREFIX_COLON + SELECTION_LIST_EL, Constants.EMPTY_ATTRS); Iterator itemIt = items.iterator(); while (itemIt.hasNext()) { SelectionListItem item = (SelectionListItem)itemIt.next(); - item.generateSaxFragment(contentHandler, locale); + item.generateSaxFragment(contentHandler, locale, formatCache); } contentHandler.endElement(Constants.WI_NS, SELECTION_LIST_EL, Constants.WI_PREFIX_COLON + SELECTION_LIST_EL); } @@ -113,10 +117,12 @@ this.label = label; } - public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException + public void generateSaxFragment(ContentHandler contentHandler, Locale locale, Convertor.FormatCache formatCache) + throws SAXException { AttributesImpl itemAttrs = new AttributesImpl(); - itemAttrs.addCDATAAttribute("value", datatype.convertToString(value)); + String stringValue = datatype.getConvertor().convertToString(value, locale, formatCache);; + itemAttrs.addCDATAAttribute("value", stringValue); contentHandler.startElement(Constants.WI_NS, ITEM_EL, Constants.WI_PREFIX_COLON + ITEM_EL, itemAttrs); contentHandler.startElement(Constants.WI_NS, LABEL_EL, Constants.WI_PREFIX_COLON + LABEL_EL, Constants.EMPTY_ATTRS); if (label != null) { @@ -124,8 +130,7 @@ interpreter.setContentHandler(contentHandler); interpreter.deserialize(label); } else { - String formattedLabel = datatype.convertToStringLocalized(value, locale); - contentHandler.characters(formattedLabel.toCharArray(), 0, formattedLabel.length()); + contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length()); } contentHandler.endElement(Constants.WI_NS, LABEL_EL, Constants.WI_PREFIX_COLON + LABEL_EL); contentHandler.endElement(Constants.WI_NS, ITEM_EL, Constants.WI_PREFIX_COLON + ITEM_EL);