View Javadoc

1   package org.apache.dvsl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.List;
23  import java.util.Stack;
24  import java.util.Map;
25  import java.util.HashMap;
26  
27  import java.io.Writer;
28  import java.io.StringWriter;
29  import java.io.Reader;
30  
31  import org.apache.velocity.context.Context;
32  import org.apache.velocity.app.VelocityEngine;
33  import org.apache.velocity.VelocityContext;
34  
35  import org.dom4j.Document;
36  import org.dom4j.Element;
37  import org.dom4j.Node;
38  import org.dom4j.DocumentException;
39  import org.dom4j.io.SAXReader;
40  
41  import org.apache.dvsl.dom4j.Dom4jNodeImpl;
42  
43  /**
44   *  <p>
45   *   Class responsible for actual transformation
46   *  of documents.
47   *  </p>
48   *
49   *  <p>
50   *  Note that this class is <em>not</em> threadsafe.
51   *  </p>
52   *
53   *  @author <a href="mailto:geirm@apache.org>Geir Magnusson Jr.</a>
54   */
55  class Transformer implements TransformTool
56  {
57      /**
58       *  Instance of VelocityEngine we are currently using.
59       *  This must be reset with a stylesheeet change
60       */
61      private VelocityEngine ve = null;
62  
63      /**
64       *  SAXReader that we reuse for every document.  Much faster.
65       */
66      private SAXReader saxReader = null;
67  
68      /**
69       *  basic context passed to us - can contain tools
70       *  and such for use.  Is protected from change via
71       *  wrapping
72       */
73      private Context baseContext;
74  
75      /**
76       *  context used during processing. Wraps the baseContext
77       */
78      private DVSLNodeContext currentContext;
79  
80      private TemplateHandler templateHandler = null;
81  
82      /**
83       *  HashMap to hold application values
84       */
85  
86      private Map appValue = new HashMap();
87  
88      /**
89       *  Sole public CTOR.  We rely on the caller to give us a
90       *  VelocityEngine ready with all macros registered.
91       *  The context is the callers context with all tools and
92       *  style drek.
93       */
94      public Transformer(VelocityEngine ve, TemplateHandler th,
95                          Context context, Map applicationValues,
96                          boolean validate)
97      {
98          this.ve = ve;
99          this.baseContext = context;
100         this.templateHandler = th;
101 
102         appValue = applicationValues;
103 
104         saxReader = new SAXReader(validate);
105     }
106 
107     /**
108      *  "Sealed for your protection."
109      */
110     private Transformer()
111     {
112     }
113 
114     /**
115      *  Method that performs the transformation on
116      *  a document
117      *
118      *  @param reader XML document char stream
119      *  @param writer Writer to output transformation to
120      */
121     long transform(Reader reader, Writer writer)
122         throws Exception
123     {
124 
125         /*
126          *  parse the document
127          */
128         Document document = saxReader.read(reader);
129 
130         return transform(document, writer);
131     }
132 
133     long transform(Document dom4jdoc, Writer writer)
134         throws Exception
135     {
136         /*
137          *  wrap the document.  We do this as we let the dom4j package
138          *  decide if we have a match against "/", so we need document
139          *  to do that
140          */
141 
142         DVSLNode root = new Dom4jNodeImpl(dom4jdoc);
143 
144         return transform(root, writer);
145     }
146 
147     protected long transform(DVSLNode root, Writer writer)
148         throws Exception
149     {
150         /*
151           *  wrap in a context to keep subsequent documents from
152           *  interacting with each other
153           */
154 
155          currentContext = new DVSLNodeContext(baseContext);
156 
157          long start = System.currentTimeMillis();
158 
159         /*
160          *  push 'this' into the context as our TransformTool
161          *  and invoke the transformation
162          */
163 
164         currentContext.put("context", this);
165 
166         invoke(root, writer);
167 
168         long end = System.currentTimeMillis();
169 
170         return end-start;
171     }
172 
173 
174     private void invoke(DVSLNode element, Writer writer)
175         throws Exception
176     {
177         String[] arr = { };
178 
179         currentContext.pushNode(element);
180 
181         templateHandler.render(element, currentContext, writer);
182 
183         currentContext.popNode();
184     }
185 
186     public Object get(String key)
187     {
188         return currentContext.get(key);
189     }
190 
191     public String applyTemplates(DVSLNode node, String xpath)
192         throws Exception
193     {
194         /*
195          *  get the nodes that was asked for
196          */
197 
198         List nodeset = node.selectNodes(xpath);
199 
200         StringWriter sw =  new StringWriter();
201 
202         for (int i = 0; i < nodeset.size(); i++)
203         {
204             DVSLNode n = (DVSLNode) nodeset.get(i);
205 
206             invoke(n, sw);
207         }
208 
209         return sw.toString();
210     }
211 
212     public String applyTemplates(DVSLNode node)
213         throws Exception
214     {
215         StringWriter sw = new StringWriter();
216 
217         invoke(node, sw);
218 
219         return sw.toString();
220     }
221 
222     public String applyTemplates()
223         throws Exception
224     {
225         return applyTemplates(currentContext.peekNode(),
226                                "*|@*|text()|comment()|processing-instruction()");
227     }
228 
229     public String applyTemplates(String path)
230         throws Exception
231     {
232         DVSLNode node = currentContext.peekNode();
233 
234         return applyTemplates(node, path);
235     }
236 
237     public String copy()
238     {
239         /*
240          *  fakie, for now
241          */
242 
243         DVSLNode node = currentContext.peekNode();
244 
245         return node.copy();
246     }
247 
248     public Object getAppValue(Object key)
249     {
250         return appValue.get(key);
251     }
252 
253     public Object putAppValue(Object key, Object value)
254     {
255         return appValue.put(key, value);
256     }
257 
258 }