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.transformation.helpers;
018:
019: import java.util.ArrayList;
020: import java.util.Map;
021:
022: import org.w3c.dom.NamedNodeMap;
023: import org.w3c.dom.Node;
024: import org.w3c.dom.NodeList;
025:
026: import org.xml.sax.Attributes;
027: import org.xml.sax.ContentHandler;
028: import org.xml.sax.SAXException;
029: import org.xml.sax.helpers.AttributesImpl;
030:
031: /**
032: * Consume elements start/end and characters events and reproduce them.
033: *
034: * WARNING: THIS CLASS DOES NOT WORK PROPERLY WITH NAMESPACES
035: *
036: * @deprecated The only user of this class (I18nTransformer) now uses ParamSaxBuffer
037: * @author <a href="mailto:mattam@netcourrier.com">Matthieu Sozeau</a>
038: * @version CVS $Id: MirrorRecorder.java 433543 2006-08-22 06:22:54Z crossley $
039: */
040: public class MirrorRecorder extends NOPRecorder implements
041: EventRecorder, Cloneable {
042:
043: private ArrayList events;
044:
045: // Used for indexing (parameters)
046: static class NullEvent implements EventRecorder {
047: private String s;
048:
049: public NullEvent(String s) {
050: this .s = s;
051: }
052:
053: public String name() {
054: return s;
055: }
056:
057: public void send(ContentHandler handler) throws SAXException {
058: }
059:
060: public Object clone() {
061: return new NullEvent(s);
062: }
063:
064: public String toString() {
065: return "{" + s + "}";
066: }
067: }
068:
069: static class StartEvent implements EventRecorder {
070: private String uri, name, raw;
071: private Attributes attr;
072:
073: public StartEvent(String namespace, String name, String raw,
074: Attributes attr) {
075: this .uri = namespace;
076: this .name = name;
077: this .raw = raw;
078: this .attr = new AttributesImpl(attr);
079: }
080:
081: public void send(ContentHandler handler) throws SAXException {
082: handler.startElement(uri, name, raw, attr);
083: }
084:
085: public Object clone() {
086: return new StartEvent(uri, name, raw, attr);
087: }
088:
089: public String toString() {
090: StringBuffer str = new StringBuffer("<" + raw);
091: if (attr != null) {
092: for (int i = 0; i < attr.getLength(); ++i) {
093: str.append(" " + attr.getQName(i) + "=\""
094: + attr.getValue(i) + "\"");
095: }
096: }
097:
098: return str.append(">").toString();
099: }
100: }
101:
102: static class EndEvent implements EventRecorder {
103: private String uri, name, raw;
104:
105: public EndEvent(String namespace, String name, String raw) {
106: this .uri = namespace;
107: this .name = name;
108: this .raw = raw;
109: }
110:
111: public Object clone() {
112: return new EndEvent(uri, name, raw);
113: }
114:
115: public void send(ContentHandler handler) throws SAXException {
116: handler.endElement(uri, name, raw);
117: }
118:
119: public String toString() {
120: return "</" + raw + ">";
121: }
122: }
123:
124: static class CharacterEvent implements EventRecorder {
125: private String ch;
126:
127: public CharacterEvent(char ary[], int start, int length) {
128: ch = new String(ary, start, length);
129: }
130:
131: public CharacterEvent(String ch) {
132: this .ch = ch;
133: }
134:
135: public Object clone() {
136: return new CharacterEvent(ch);
137: }
138:
139: public void send(ContentHandler handler) throws SAXException {
140: handler.characters(ch.toCharArray(), 0, ch.length());
141: }
142:
143: public String toString() {
144: return ch;
145: }
146: }
147:
148: public MirrorRecorder() {
149: this .events = new ArrayList();
150: }
151:
152: public MirrorRecorder(Node n) {
153: this .events = new ArrayList();
154:
155: if (n != null) {
156: NodeList childs = n.getChildNodes();
157: for (int i = 0; i < childs.getLength(); ++i) {
158: try {
159: nodeToEvents(childs.item(i));
160: } catch (SAXException e) {
161: // FIXME: what to do?
162: }
163: }
164: }
165: }
166:
167: private void nodeToEvents(Node n) throws SAXException {
168: switch (n.getNodeType()) {
169: case Node.ELEMENT_NODE:
170: Attributes attrs;
171: if (n.getAttributes() instanceof Attributes) {
172: attrs = (Attributes) n.getAttributes();
173: } else {
174: NamedNodeMap map = n.getAttributes();
175: attrs = new AttributesImpl();
176:
177: for (int i = 0; i < map.getLength(); ++i) {
178: Node node = map.item(i);
179: final String ns = node.getNamespaceURI() == null ? ""
180: : node.getNamespaceURI();
181: final String ln = node.getLocalName() == null ? node
182: .getNodeName()
183: : node.getLocalName();
184: ((AttributesImpl) attrs).addAttribute(ns, ln, node
185: .getNodeName(), "CDATA", node
186: .getNodeValue());
187: }
188: }
189:
190: final String ns = n.getNamespaceURI() == null ? "" : n
191: .getNamespaceURI();
192: final String ln = n.getLocalName() == null ? n
193: .getNodeName() : n.getLocalName();
194: startElement(ns, ln, n.getNodeName(), attrs);
195: if (n.hasChildNodes()) {
196: NodeList childs = n.getChildNodes();
197: for (int i = 0; i < childs.getLength(); ++i) {
198: nodeToEvents(childs.item(i));
199: }
200: }
201:
202: endElement(ns, ln, n.getNodeName());
203: break;
204: case Node.CDATA_SECTION_NODE:
205: case Node.TEXT_NODE:
206: characters(n.getNodeValue());
207: break;
208: }
209: }
210:
211: public MirrorRecorder(MirrorRecorder n) {
212: this .events = new ArrayList();
213: for (int i = 0; i < n.events.size(); ++i) {
214: EventRecorder e = (EventRecorder) n.events.get(i);
215: this .events.add(e.clone());
216: }
217: }
218:
219: public Object clone() {
220: return new MirrorRecorder(this );
221: }
222:
223: public void startElement(String namespace, String name, String raw,
224: Attributes attr) throws SAXException {
225: events.add(new StartEvent(namespace, name, raw, attr));
226: }
227:
228: public void endElement(String namespace, String name, String raw)
229: throws SAXException {
230: events.add(new EndEvent(namespace, name, raw));
231: }
232:
233: public void characters(char ary[], int start, int length)
234: throws SAXException {
235: characters(new String(ary, start, length));
236: }
237:
238: public void characters(String tmp) throws SAXException {
239: int i = 0, j = 0;
240:
241: while (tmp.length() > 0) {
242: i = tmp.indexOf('{', i);
243: if (i == -1) {
244: events.add(new CharacterEvent(tmp));
245: return;
246: } else {
247: if (i >= 0) {
248: events.add(new CharacterEvent(tmp.substring(0, i)));
249: }
250:
251: j = tmp.indexOf('}', i);
252: if (j != -1) {
253: events.add(new NullEvent(tmp.substring(i + 1, j)));
254: tmp = tmp.substring(j + 1, tmp.length());
255: i = 0;
256: }
257: }
258: }
259: }
260:
261: public void send(ContentHandler handler) throws SAXException {
262: for (int i = 0; i < events.size(); ++i) {
263: ((EventRecorder) (events.get(i))).send(handler);
264: }
265: }
266:
267: public void send(ContentHandler handler, Map params)
268: throws SAXException {
269: EventRecorder param;
270:
271: for (int i = 0; i < events.size(); ++i) {
272: if (events.get(i) instanceof NullEvent) {
273: param = (EventRecorder) params.get(((NullEvent) events
274: .get(i)).name());
275: if (param != null)
276: param.send(handler);
277: } else {
278: ((EventRecorder) (events.get(i))).send(handler);
279: }
280: }
281: }
282:
283: public String text() {
284: StringBuffer s = new StringBuffer();
285:
286: for (int i = 0; i < events.size(); ++i) {
287: s.append(events.get(i).toString());
288: }
289: return (s.toString());
290: }
291:
292: public String toString() {
293: StringBuffer s = new StringBuffer("MirrorRecorder: ");
294: s.append(String.valueOf(events.size()) + " event(s)");
295: s.append("\ntext: ");
296: for (int i = 0; i < events.size(); ++i) {
297: if (events.get(i) instanceof CharacterEvent) {
298: s.append(events.get(i).toString());
299: }
300: }
301:
302: return s.toString();
303: }
304:
305: public void recycle() {
306: events.clear();
307: }
308:
309: public boolean empty() {
310: return events.size() == 0;
311: }
312: }
|