001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.template.xml;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.apache.cocoon.xml.XMLConsumer;
024: import org.xml.sax.Attributes;
025: import org.xml.sax.ContentHandler;
026: import org.xml.sax.Locator;
027: import org.xml.sax.SAXException;
028: import org.xml.sax.SAXParseException;
029: import org.xml.sax.helpers.AttributesImpl;
030:
031: /**
032: * @version $Id: AttributeAwareXMLConsumerImpl.java 449189 2006-09-23 06:52:29Z crossley $
033: */
034: public class AttributeAwareXMLConsumerImpl implements
035: AttributeAwareXMLConsumer {
036:
037: private StartElement currentElement;
038: private List saxbits;
039: private Locator locator;
040:
041: private XMLConsumer delegate;
042:
043: public AttributeAwareXMLConsumerImpl(XMLConsumer consumer) {
044: this .delegate = consumer;
045: this .saxbits = new ArrayList();
046: }
047:
048: public void setDocumentLocator(Locator locator) {
049: this .locator = locator;
050: delegate.setDocumentLocator(locator);
051: }
052:
053: public void startDocument() throws SAXException {
054: delegate.startDocument();
055: }
056:
057: public void endDocument() throws SAXException {
058: playCache();
059: delegate.endDocument();
060: }
061:
062: public void startPrefixMapping(String prefix, String uri)
063: throws SAXException {
064: playCache();
065: delegate.startPrefixMapping(prefix, uri);
066: }
067:
068: public void endPrefixMapping(String prefix) throws SAXException {
069: playCache();
070: delegate.endPrefixMapping(prefix);
071: }
072:
073: public void startElement(String namespaceURI, String localName,
074: String qName, Attributes attrs) throws SAXException {
075: playCache();
076: this .currentElement = new StartElement(namespaceURI, localName,
077: qName, attrs);
078: }
079:
080: public void endElement(String namespaceURI, String localName,
081: String qName) throws SAXException {
082: playCache();
083: delegate.endElement(namespaceURI, localName, qName);
084: }
085:
086: public void characters(char[] ch, int start, int length)
087: throws SAXException {
088: // TODO: should we allow to emit characters before adding an attribute?
089: if (this .currentElement != null)
090: this .saxbits.add(new Characters(ch, start, length));
091: else
092: delegate.characters(ch, start, length);
093:
094: }
095:
096: public void ignorableWhitespace(char[] ch, int start, int length)
097: throws SAXException {
098: if (this .currentElement != null)
099: this .saxbits
100: .add(new IgnorableWhitespace(ch, start, length));
101: else
102: delegate.ignorableWhitespace(ch, start, length);
103: }
104:
105: public void processingInstruction(String target, String data)
106: throws SAXException {
107: playCache();
108: delegate.processingInstruction(target, data);
109: }
110:
111: public void skippedEntity(String name) throws SAXException {
112: playCache();
113: delegate.skippedEntity(name);
114: }
115:
116: public void startDTD(String name, String publicId, String systemId)
117: throws SAXException {
118: playCache();
119: delegate.startDTD(name, publicId, systemId);
120: }
121:
122: public void endDTD() throws SAXException {
123: playCache();
124: delegate.endDTD();
125: }
126:
127: public void startEntity(String name) throws SAXException {
128: playCache();
129: delegate.startEntity(name);
130: }
131:
132: public void endEntity(String name) throws SAXException {
133: playCache();
134: delegate.endEntity(name);
135: }
136:
137: public void startCDATA() throws SAXException {
138: playCache();
139: delegate.startCDATA();
140: }
141:
142: public void endCDATA() throws SAXException {
143: playCache();
144: delegate.endCDATA();
145: }
146:
147: public void comment(char[] ch, int start, int length)
148: throws SAXException {
149: playCache();
150: delegate.comment(ch, start, length);
151: }
152:
153: public void attribute(String uri, String localName, String qName,
154: String type, String value) throws SAXException {
155: if (this .currentElement == null)
156: throw new SAXParseException(
157: "attribute event not allowed here", this .locator);
158: else {
159: this .currentElement.attribute(uri, localName, qName, type,
160: value);
161: // if between currentElement and jx:attribute only whitespace
162: // was recorded - skip it
163: boolean whitespaceOnly = true;
164: Iterator it = this .saxbits.iterator();
165: while (it.hasNext()) {
166: SaxBit saxBit = (SaxBit) it.next();
167: if (!(saxBit instanceof IgnorableWhitespace))
168: whitespaceOnly = false;
169: }
170: if (whitespaceOnly)
171: this .saxbits.clear();
172: }
173: }
174:
175: interface SaxBit {
176: public void send(ContentHandler contentHandler)
177: throws SAXException;
178: }
179:
180: private class StartElement implements SaxBit {
181: private String namespaceURI;
182: private String localName;
183: private String qName;
184: private AttributesImpl attrs;
185:
186: public StartElement(String namespaceURI, String localName,
187: String qName, Attributes attrs) {
188: this .namespaceURI = namespaceURI;
189: this .localName = localName;
190: this .qName = qName;
191: this .attrs = new AttributesImpl(attrs);
192: }
193:
194: public void send(ContentHandler contentHandler)
195: throws SAXException {
196: contentHandler.startElement(this .namespaceURI,
197: this .localName, this .qName, this .attrs);
198: }
199:
200: public void attribute(String uri, String localName,
201: String qName, String type, String value) {
202: this .attrs.addAttribute(uri, localName, qName, type, value);
203: }
204: }
205:
206: public final static class Characters implements SaxBit {
207: public final char[] ch;
208:
209: public Characters(char[] ch, int start, int length) {
210: this .ch = new char[length];
211: System.arraycopy(ch, start, this .ch, 0, length);
212: }
213:
214: public void send(ContentHandler contentHandler)
215: throws SAXException {
216: contentHandler.characters(ch, 0, ch.length);
217: }
218: }
219:
220: public final static class IgnorableWhitespace implements SaxBit {
221: public final char[] ch;
222:
223: public IgnorableWhitespace(char[] ch, int start, int length) {
224: this .ch = new char[length];
225: System.arraycopy(ch, start, this .ch, 0, length);
226: }
227:
228: public void send(ContentHandler contentHandler)
229: throws SAXException {
230: contentHandler.ignorableWhitespace(ch, 0, ch.length);
231: }
232: }
233:
234: public void playCache() throws SAXException {
235: if (this .currentElement != null) {
236: this .currentElement.send(delegate);
237: this .currentElement = null;
238: }
239:
240: Iterator it = this .saxbits.iterator();
241: while (it.hasNext()) {
242: SaxBit saxBit = (SaxBit) it.next();
243: saxBit.send(delegate);
244: }
245: this.saxbits.clear();
246: }
247: }
|