View Javadoc

1   package net.sf.tomp.xtcl.command;
2   
3   import java.io.PrintStream;
4   import java.util.ArrayList;
5   import java.util.Iterator;
6   import java.util.List;
7   
8   import javax.xml.parsers.SAXParserFactory;
9   import javax.xml.transform.Result;
10  import javax.xml.transform.Source;
11  import javax.xml.transform.Templates;
12  import javax.xml.transform.Transformer;
13  import javax.xml.transform.TransformerException;
14  import javax.xml.transform.TransformerFactory;
15  import javax.xml.transform.sax.SAXSource;
16  import javax.xml.transform.sax.SAXTransformerFactory;
17  import javax.xml.transform.sax.TransformerHandler;
18  import javax.xml.transform.stream.StreamResult;
19  import javax.xml.transform.stream.StreamSource;
20  
21  import net.sf.tomp.xtcl.Context;
22  import net.sf.tomp.xtcl.filter.HasOutputProperties;
23  import net.sf.tomp.xtcl.filter.HasOutputPropertiesWrapper;
24  
25  import org.xml.sax.XMLFilter;
26  import org.xml.sax.XMLReader;
27  import org.xml.sax.helpers.LocatorImpl;
28  
29  /***
30   * Command to assemble and store a transformation chain
31   * 
32   * @author tomp
33   */
34  public class Chain extends VarCommand {
35  	
36      /*** reference to the source */
37      protected String sourceRef;
38  
39      /*** reference to the filters or styles in the chain */
40      protected List filterStyleRefs = new ArrayList();
41  
42      /*** reference to the result of the chain */
43      protected String resultRef;
44  
45      /***
46       * sets source ref name
47       * 
48       * @param s source ref name
49       */
50      public void setSourceRef(String s) {
51          sourceRef = s;
52      }
53  
54      /***
55       * adds filter or style reference
56       * 
57       * @param s filter or style reference
58       */
59      public void addFilterStyleRef(String s) {
60          filterStyleRefs.add(s); 
61      }
62  
63      /***
64       * DOCUMENT ME!
65       * 
66       * @param s DOCUMENT ME!
67       */
68      public void setResultRef(String s) {
69          resultRef = s;
70      }
71  
72      /***
73       * Creates and executes a chain transformation by
74       * chaining SAX filters and XSLT-based SAX filters. 
75       * 
76       * @param context
77       * @return 
78       * @throws Exception 
79       */
80      public int execute(Context context) throws Exception {
81          try {
82              TransformerFactory tf = context.getTransformerFactory();
83  
84              if (!tf.getFeature(SAXSource.FEATURE)) {
85                  throw new TransformerException("Not a SAXTransformerFactory");
86              }
87  
88              SAXTransformerFactory stf = (SAXTransformerFactory) tf;
89  
90              SAXParserFactory spf = context.getSAXParserFactory();
91  
92              spf.setNamespaceAware(true);
93  
94              XMLReader xr = spf.newSAXParser().getXMLReader();
95  
96              Source source = sourceRef.startsWith("$") ? context
97                      .refToSource(sourceRef) : new StreamSource(context
98                      .getFile(sourceRef));
99  
100             Result result = resultRef.startsWith("$") ? context
101                     .refToResult(resultRef) : new StreamResult(context
102                     .getFile(resultRef));
103 
104             // if source is SAXSource, use its XMLReader as the first reader 'xr'
105             if (source instanceof SAXSource) {
106                 xr = ((SAXSource) source).getXMLReader();
107             }
108             XMLReader f = xr;
109             XMLReader prev = xr;
110 
111             Iterator i = filterStyleRefs.iterator();
112 
113             if (i.hasNext()) {
114                 // nonempty chain, at least one style/filter
115                 while (i.hasNext()) {
116                     Templates t = null;
117                     TransformerHandler th = null;
118 
119                     String ref = (String) i.next();
120                     Object value = null;
121 
122                     if (ref.startsWith("$")) {
123                         value = context.get(ref);
124 
125                         //System.out.println("\nREF
126                         // "+ref+"=>"+context.get(ref));
127                         if (!(value instanceof XMLFilter)) {
128                             t = context.refToStyle(ref);
129                         }
130                     } else {
131                         // style filename
132                         t = stf.newTemplates(new StreamSource(context
133                                 .getFile(ref)));
134                     }
135 
136                     // FIXME: what if XMLFilter is the last
137                     if (i.hasNext()) {
138                         f = (t == null) ? context.refToXMLFilter(ref) : stf
139                                 .newXMLFilter(t);
140 
141                         //System.out.println("XMLFilter="+f);
142                         ((XMLFilter) f).setParent(prev);
143 
144                         /*
145                          * if(f instanceof ContentHandler) { Locator loc = new
146                          * SimpleLocator(source.getSystemId());
147                          * System.out.println(f+".setDocumentLocator="+loc);
148                          * ((ContentHandler)f).setDocumentLocator(loc); }
149                          */
150                     } else {
151                         // last style/filter
152                         if (value instanceof XMLFilter) {
153                             f = context.refToXMLFilter(ref);
154 
155                             //System.out.println(">>> SET PARENT TO "+f+"
156                             // "+prev);
157                             ((XMLFilter) f).setParent(prev);
158 
159                             // FIXME changed 4/2/04
160                             /*
161                              * if(f instanceof ContentHandler) { Locator loc =
162                              * new SimpleLocator(source.getSystemId());
163                              * System.out.println(f+".setDocumentLocator="+loc);
164                              * //((ContentHandler)f).setDocumentLocator(loc); }
165                              */
166                             th = stf.newTransformerHandler();
167 
168                             //System.out.println("newTransformerHandler="+th);
169                             if (f instanceof HasOutputProperties) {
170                                 ((HasOutputProperties) f)
171                                         .setOutputPropertiesListener(new HasOutputPropertiesWrapper(
172                                                 th));
173                             }
174                         } else {
175                             //System.out.println("XMLFilter="+f);
176                             th = stf.newTransformerHandler(t);
177 
178                             /*
179                              * Locator loc = new
180                              * SimpleLocator(source.getSystemId());
181                              * System.out.println(th+".setDocumentLocator="+loc);
182                              * th.setDocumentLocator(loc);
183                              */
184                         }
185 
186                         f.setContentHandler(th);
187                         f
188                                 .setProperty(
189                                         "http://xml.org/sax/properties/lexical-handler",
190                                         th);
191                         th.setResult(result);
192 
193                         /*                        System.out.println("NOW f=" + f + " is PARSING source="
194                          + source);
195                          System.out.println("NOW f.getParent()="
196                          + ((XMLFilter) f).getParent());
197                          */f.parse(SAXSource.sourceToInputSource(source));
198 
199                         //System.out.println("NOW PARSING to result="+result);
200                         //System.out.println("END OF PARSING");
201                     }
202 
203                     prev = f;
204                 }
205             } else {
206                 //System.out.println("in CHAIN: empty transformation");
207                 Transformer transf = tf.newTransformer();
208 
209                 transf.transform(source, result);
210             }
211 
212             return done(context, 0);
213         } catch (TransformerException te) {
214             PrintStream out = context.getOut();
215 
216             te.printStackTrace(out);
217 
218             return done(context, 1);
219         }
220     }
221 
222     /***
223      * @return "CHAIN " + sourceRef + " -> " + resultRef + " STYLES/FILTERS ("
224                 + listList(filterStyleRefs) + ")";
225      */
226     public String toString() {
227         return "CHAIN " + sourceRef + " -> " + resultRef + " STYLES/FILTERS ("
228                 + listList(filterStyleRefs) + ")";
229     }
230 
231     static class SimpleLocator extends LocatorImpl {
232         public SimpleLocator(String systemId) {
233             setSystemId(systemId);
234             setPublicId(systemId);
235             setColumnNumber(-1);
236             setLineNumber(-1);
237         }
238 
239         public String toString() {
240             return "SimpleLocator.systemId=" + getSystemId();
241         }
242     }
243 }
244 
245 /*
246  * The contents of this file are subject to the Mozilla Public License Version
247  * 1.1 (the "License"); you may not use this file except in compliance with the
248  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
249  * Software distributed under the License is distributed on an "AS IS" basis,
250  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
251  * the specific language governing rights and limitations under the License. The
252  * Original Code is: all this file. The Initial Developer of the Original Code
253  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
254  */