001: /* Transformer.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Aug 28 13:57:53 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zml;
020:
021: import java.util.Iterator;
022: import java.io.File;
023: import java.io.InputStream;
024: import java.io.Reader;
025: import java.io.Writer;
026: import java.io.StringReader;
027: import java.io.StringWriter;
028: import java.io.IOException;
029: import java.net.URL;
030: import javax.xml.transform.Source;
031: import javax.xml.transform.Result;
032: import javax.xml.transform.dom.DOMSource;
033: import javax.xml.transform.stream.StreamSource;
034: import javax.xml.transform.stream.StreamResult;
035:
036: import org.zkoss.idom.Document;
037:
038: import org.zkoss.zk.ui.WebApp;
039: import org.zkoss.zk.ui.Component;
040: import org.zkoss.zk.ui.AbstractComponent;
041: import org.zkoss.zk.ui.UiException;
042:
043: /**
044: * XML transformer.
045: *
046: * @author tomyeh
047: */
048: public class Transformer extends AbstractComponent {
049: private Object _xsl;
050:
051: /** Returns the XSL (Extensible Stylesheet Language), or null
052: * if not available.
053: *
054: * @see #setXsl(String)
055: * @see #setXsl(URL)
056: * @see #setXsl(File)
057: * @see #setXsl(Source)
058: */
059: public Object getXsl() {
060: return _xsl;
061: }
062:
063: /** Sets the XSL with the resource path.
064: * The resource must be retrievable by use of {@link WebApp#getResource}.
065: */
066: public void setXsl(String xsl) {
067: _xsl = xsl;
068: }
069:
070: /** Sets the XSL with a file.
071: */
072: public void setXsl(File xsl) {
073: _xsl = xsl;
074: }
075:
076: /** Sets the XSL with an URL.
077: */
078: public void setXsl(URL xsl) {
079: _xsl = xsl;
080: }
081:
082: /** Sets the XSL with an input stream.
083: */
084: public void setXsl(InputStream xsl) {
085: _xsl = xsl;
086: }
087:
088: /** Sets the XSL with a reader.
089: */
090: public void setXsl(Reader xsl) {
091: _xsl = xsl;
092: }
093:
094: /** Sets the XSL with a XML source.
095: */
096: public void setXsl(Source xsl) {
097: _xsl = xsl;
098: }
099:
100: /** Sets the XSL with a document.
101: */
102: public void setXsl(org.w3c.dom.Document xsl) {
103: _xsl = xsl;
104: }
105:
106: /** Sets the XSL with a iDOM document.
107: */
108: public void setXsl(Document xsl) {
109: _xsl = xsl;
110: }
111:
112: //Component//
113: public void redraw(Writer out) throws IOException {
114: final Source src;
115: {
116: final StringWriter sw = new StringWriter(1024);
117: for (Iterator it = getChildren().iterator(); it.hasNext();)
118: ((Component) it.next()).redraw(sw);
119: src = new StreamSource(new StringReader(sw.toString()));
120: }
121:
122: final Source xsl;
123: if (_xsl instanceof String) {
124: InputStream is = getDesktop().getWebApp()
125: .getResourceAsStream(
126: getDesktop().getExecution().toAbsoluteURI(
127: (String) _xsl, false));
128: if (is == null)
129: throw new UiException("Resouce not found, " + _xsl);
130: xsl = new StreamSource(is);
131: } else if (_xsl instanceof File) {
132: xsl = new StreamSource((File) _xsl);
133: } else if (_xsl instanceof InputStream) {
134: xsl = new StreamSource((InputStream) _xsl);
135: } else if (_xsl instanceof Reader) {
136: xsl = new StreamSource((Reader) _xsl);
137: } else if (_xsl instanceof URL) {
138: xsl = new StreamSource(((URL) _xsl).openStream());
139: } else if (_xsl instanceof org.w3c.dom.Document) { //include iDOM
140: xsl = new DOMSource((org.w3c.dom.Document) _xsl);
141: } else if (_xsl == null) {
142: xsl = null;
143: } else {
144: throw new InternalError("Unknown XSL: "
145: + _xsl.getClass().getName());
146: }
147:
148: final StringWriter result = new StringWriter();
149:
150: try {
151: new org.zkoss.idom.transform.Transformer(xsl).transform(
152: src, new StreamResult(result));
153: } catch (Throwable ex) {
154: throw UiException.Aide.wrap(ex);
155: }
156:
157: //We have to stripe <?xml...?> since UiEngine generates spaces
158: //before this component
159: final StringBuffer sb = result.getBuffer();
160: int j = 0;
161: l_out: for (int len = sb.length(); j < len; j++) {
162: char cc = sb.charAt(j);
163: if (isSpace(cc))
164: continue;
165:
166: if (cc == '<') {
167: int k = j;
168: if (isChar(sb, ++k, '?') && isChar(sb, ++k, 'x')
169: && isChar(sb, ++k, 'm') && isChar(sb, ++k, 'l')
170: && ++k < len && isSpace(sb.charAt(k))) {
171: while (++k < len) {
172: cc = sb.charAt(k);
173: if (cc == '>') {
174: j = k + 1;
175: break l_out; //done
176: }
177: }
178: }
179: }
180: break;
181: }
182: out.write(sb.substring(j));
183: }
184:
185: private static boolean isSpace(char cc) {
186: return cc == ' ' || cc == '\t' || cc == '\n' || cc == '\r';
187: }
188:
189: private static boolean isChar(StringBuffer sb, int j, char cc) {
190: return j < sb.length() && sb.charAt(j) == cc;
191: }
192: }
|