001: /*
002: * Copyright 2007 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.i18n.impl;
017:
018: import org.outerj.daisy.xmlutil.LocalSAXParserFactory;
019: import org.outerj.daisy.xmlutil.SaxBuffer;
020: import org.outerj.daisy.i18n.DResourceBundle;
021: import org.outerj.daisy.i18n.I18nMessage;
022: import org.xml.sax.*;
023:
024: import javax.xml.parsers.SAXParserFactory;
025: import javax.xml.parsers.SAXParser;
026: import javax.xml.parsers.ParserConfigurationException;
027: import java.io.IOException;
028: import java.util.Map;
029: import java.util.HashMap;
030:
031: public class DResourceBundleFactory {
032: /**
033: * Builds a resource bundle from an XML file, in "Cocoon i18n transformer" format.
034: *
035: * <p>This means something like this:
036: * <pre>
037: * <catalogue>
038: * <message key='something'>something</message>
039: * </catalogue>
040: *
041: * <p>Messages can contain mixed content (there's no special treatment to make sure
042: * namespace prefix declaration are included though, so better not use namespaces).
043: *
044: * </pre>
045: * @param is <b>the caller is responsible for closing the input stream!</b>
046: */
047: public static DResourceBundle build(InputSource is)
048: throws SAXException, ParserConfigurationException,
049: IOException {
050: SAXParserFactory parserFactory = LocalSAXParserFactory
051: .getSAXParserFactory();
052: SAXParser parser = parserFactory.newSAXParser();
053: XmlResourceBundleHandler handler = new XmlResourceBundleHandler();
054: parser.getXMLReader().setContentHandler(handler);
055: parser.getXMLReader().parse(is);
056: return new DResourceBundleImpl(handler.getEntries());
057: }
058:
059: private static class XmlResourceBundleHandler implements
060: ContentHandler {
061: private SaxBuffer buffer;
062: private int elementNesting = 0;
063: private String key;
064: private Map<String, I18nMessage> entries = new HashMap<String, I18nMessage>();
065:
066: public Map<String, I18nMessage> getEntries() {
067: return entries;
068: }
069:
070: public void startElement(String uri, String localName,
071: String qName, Attributes atts) throws SAXException {
072: if (buffer != null) {
073: buffer.startElement(uri, localName, qName, atts);
074: } else if (elementNesting == 0) {
075: if (!uri.equals("") || !localName.equals("catalogue")) {
076: throw new SAXException(
077: "Root element of resource bundle should be called 'catalogue'.");
078: }
079: } else if (elementNesting == 1 && uri.equals("")
080: && localName.equals("message")) {
081: key = atts.getValue("key");
082: if (key.trim().length() == 0)
083: key = null;
084: if (key != null) // <message> tags with missing key attribute are silently skipped
085: buffer = new SaxBuffer();
086: }
087:
088: elementNesting++;
089: }
090:
091: public void endElement(String uri, String localName,
092: String qName) throws SAXException {
093: if (elementNesting == 2 && buffer != null) {
094: entries.put(key, new I18nMessageImpl(buffer));
095: key = null;
096: buffer = null;
097: } else if (buffer != null) {
098: buffer.endElement(uri, localName, qName);
099: }
100: elementNesting--;
101: }
102:
103: public void setDocumentLocator(Locator locator) {
104: // do nothing
105: }
106:
107: public void startDocument() throws SAXException {
108: // do nothing
109: }
110:
111: public void endDocument() throws SAXException {
112: // do nothing
113: }
114:
115: public void startPrefixMapping(String prefix, String uri)
116: throws SAXException {
117: if (buffer != null)
118: buffer.startPrefixMapping(prefix, uri);
119: }
120:
121: public void endPrefixMapping(String prefix) throws SAXException {
122: if (buffer != null)
123: buffer.endPrefixMapping(prefix);
124: }
125:
126: public void characters(char ch[], int start, int length)
127: throws SAXException {
128: if (buffer != null)
129: buffer.characters(ch, start, length);
130: }
131:
132: public void ignorableWhitespace(char ch[], int start, int length)
133: throws SAXException {
134: if (buffer != null)
135: buffer.ignorableWhitespace(ch, start, length);
136: }
137:
138: public void processingInstruction(String target, String data)
139: throws SAXException {
140: if (buffer != null)
141: buffer.processingInstruction(target, data);
142: }
143:
144: public void skippedEntity(String name) throws SAXException {
145: if (buffer != null)
146: buffer.skippedEntity(name);
147: }
148: }
149: }
|