• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 package org.apache.qetest.xslwrapper;
22 
23 import java.util.Enumeration;
24 import java.util.Hashtable;
25 import java.util.Properties;
26 
27 /**
28  * A few default implementations of TransformWrapper methods.
29  *
30  * A TransformWrapperHelper implements a few of the common methods
31  * from TransformWrapper that don't directly interact with the
32  * underlying processor.  Individual wrapper implementations are
33  * free to extend this class to get some free code.
34  *
35  * @author Shane Curcuru
36  * @version $Id$
37  */
38 public abstract class TransformWrapperHelper implements TransformWrapper
39 {
40 
41     /** Constant denoting that indent should not be set.  */
42     protected static final int NO_INDENT = -2;
43 
44 
45     /**
46      * Current number of spaces to indent, default: NO_INDENT.
47      * Users call setAttribute(ATTRIBUTE_INDENT, int) to set this.
48      * If it is set, it will be applied to an underlying processor
49      * during each transform operation, where supported.
50      */
51     protected int m_indent = NO_INDENT;
52 
53 
54     /**
55      * Allows the user to ask the wrapper to set specific
56      * attributes on the underlying implementation.
57      *
58      * Supported attributes in this class include:
59      * ATTRIBUTE_INDENT
60      *
61      * //@todo define behavior for subclasses who want our default
62      * behavior but also want to throw the exception for
63      * attributes that are not recognized.
64      *
65      * @param name The name of the attribute.
66      * @param value The value of the attribute.
67      *
68      * @throws IllegalArgumentException thrown only if we can't
69      * parse an int from the value
70      *
71      * @see #ATTRIBUTE_INDENT
72      */
setAttribute(String name, Object value)73     public void setAttribute(String name, Object value)
74         throws IllegalArgumentException
75     {
76         if (ATTRIBUTE_INDENT.equals(name))
77         {
78             try
79             {
80                 m_indent = (new Integer((String)value)).intValue();
81             }
82             catch (Exception e)
83             {
84                 throw new IllegalArgumentException("setAttribute: bad value: " + value);
85             }
86         }
87     }
88 
89 
90     /**
91      * Allows the user to set specific attributes on the testing
92      * utility or it's underlying product object under test.
93      *
94      * This method should attempt to set any applicable attributes
95      * found in the given attrs onto itself, and will ignore any and
96      * all attributes it does not recognize.  It should never
97      * throw exceptions.  This method may overwrite any previous
98      * attributes that were set.  Currently since this takes a
99      * Properties block you may only be able to set objects that
100      * are Strings, although individual implementations may
101      * attempt to use Hashtable.get() on only the local part.
102      *
103      * Currently unimplemented; no-op.
104      *
105      * @param attrs Props of various name, value attrs.
106      */
applyAttributes(Properties attrs)107     public void applyAttributes(Properties attrs)
108     {
109         /* no-op */;
110     }
111 
112 
113     /**
114      * Allows the user to retrieve specific attributes on the
115      * underlying implementation.
116      *
117      * This class merely returns the indent for ATTRIBUTE_INDENT.
118      *
119      * //@todo define behavior for subclasses who want our default
120      * behavior but also want to throw the exception for
121      * attributes that are not recognized.
122      *
123      * @param name The name of the attribute.
124      * @return value The value of the attribute.
125      * @throws IllegalArgumentException not thrown from this class
126      *
127      * @see #ATTRIBUTE_INDENT
128      */
getAttribute(String name)129     public Object getAttribute(String name) throws IllegalArgumentException
130     {
131         if (ATTRIBUTE_INDENT.equals(name))
132         {
133             return new Integer(m_indent);
134         }
135         return null;
136     }
137 
138 
139     /** If our wrapper has a built stylesheet ready.  */
140     protected boolean m_stylesheetReady = false;
141 
142 
143     /**
144      * Reports if a pre-built/pre-compiled stylesheet is ready;
145      * presumably built by calling buildStylesheet(xslName).
146      *
147      * @return true if one is ready; false otherwise
148      *
149      * @see #buildStylesheet(String xslName)
150      */
isStylesheetReady()151     public boolean isStylesheetReady()
152     {
153         return m_stylesheetReady;
154     }
155 
156 
157     /** Set of stylesheet parameters for use in transforms.  */
158     protected Hashtable m_params = null;
159 
160 
161     /**
162      * Set a stylesheet parameter for use in later transforms.
163      *
164      * This method merely stores the triple for use later in a
165      * transform operation.  Note that the actual mechanisims for
166      * setting parameters in implementation differ, especially with
167      * regards to namespaces.
168      *
169      * Note that the namespace may not contain the "{" or "}"
170      * characters, since these would be illegal XML namespaces
171      * anyways; an IllegalArgumentException will be thrown.
172      * Note that the name may not begin with the "{"
173      * character, since it would likely be an illegal XML name
174      * anyways; an IllegalArgumentException will be thrown.
175      *
176      * @param namespace for the parameter
177      * @param name of the parameter
178      * @param value of the parameter
179      *
180      * @throws IllegalArgumentException thrown if the namespace
181      * appears to be illegal.
182      */
setParameter(String namespace, String name, Object value)183     public void setParameter(String namespace, String name, Object value)
184         throws IllegalArgumentException
185     {
186         if (null != namespace)
187         {
188             if ((namespace.indexOf("{") > -1)
189                 || (namespace.indexOf("}") > -1))
190                 throw new IllegalArgumentException(
191                     "setParameter: illegal namespace includes brackets: " + namespace);
192         }
193         if (null != name)
194         {
195             if (name.startsWith("{"))
196                 throw new IllegalArgumentException(
197                     "setParameter: illegal name begins with bracket: " + name);
198         }
199 
200         if (null == m_params)
201             m_params = new Hashtable();
202 
203         if (null != namespace)
204         {
205             m_params.put("{" + namespace + "}" + name, value);
206         }
207         else
208         {
209             m_params.put(name, value);
210         }
211     }
212 
213 
214     /**
215      * Get a parameter that was set with setParameter.
216      *
217      * Only returns parameters set locally, not parameters exposed
218      * by the underlying processor implementation.  Not terribly useful
219      * but I always like providing gets for any sets I define.
220      *
221      * @param namespace for the parameter
222      * @param name of the parameter
223      *
224      * @param value of the parameter; null if not found
225      */
getParameter(String namespace, String name)226     public Object getParameter(String namespace, String name)
227     {
228         if (null == m_params)
229             return null;
230 
231         if (null != namespace)
232         {
233             return m_params.get("{" + namespace + "}" + name);
234         }
235         else
236         {
237             return m_params.get(name);
238         }
239     }
240 
241 
242     /**
243      * Apply the parameters that were set with setParameter to
244      * our underlying processor implementation.
245      *
246      * Subclasses may call this to apply all set parameters during
247      * each transform if they override the applyParameter() method
248      * to set a single parameter.
249      *
250      * This is a convenience method for getting data out of
251      * m_params that was encoded by our setParameter().
252      *
253      * @param passThru to be passed to each applyParameter() method
254      * call - for TrAX, you might pass a Transformer object.
255      */
applyParameters(Object passThru)256     protected void applyParameters(Object passThru)
257     {
258         if (null == m_params)
259             return;
260 
261         for (Enumeration keys = m_params.keys();
262              keys.hasMoreElements();
263              /* no increment portion */ )
264         {
265             String namespace = null;
266             String name = null;
267             String key = keys.nextElement().toString();
268             //@todo compare with TransformerImpl.setParameter's use of a StringTokenizer(..., "{}"...
269             // Decode the namespace, if present
270             if (key.startsWith("{"))
271             {
272                 int idx = key.indexOf("}");
273                 namespace = key.substring(1, idx);
274                 name = key.substring(idx + 1); //@todo check for out of range?
275             }
276             else
277             {
278                 // namespace stays null
279                 name = key;
280             }
281             // Call subclassed worker method for each parameter
282             applyParameter(passThru, namespace, name, m_params.get(key));
283         }
284     }
285 
286 
287     /**
288      * Apply a single parameter to our underlying processor
289      * implementation: must be overridden.
290      *
291      * Subclasses must override; this class will throw an
292      * IllegalStateException since we can't do anything.
293      *
294      * @param passThru to be passed to each applyParameter() method
295      * call - for TrAX, you might pass a Transformer object.
296      * @param namespace for the parameter, may be null
297      * @param name for the parameter, should not be null
298      * @param value for the parameter, may be null
299      */
applyParameter(Object passThru, String namespace, String name, Object value)300     protected void applyParameter(Object passThru, String namespace,
301                                   String name, Object value)
302     {
303         throw new IllegalStateException("TransformWrapperHelper.applyParameter must be overridden!");
304     }
305 
306 
307     /**
308      * Reset our parameters and wrapper state, and optionally
309      * force creation of a new underlying processor implementation.
310      *
311      * This class clears the indent and any parameters.
312      * Subclasses are free to call us to get this default behavior
313      * or not.  Note that subclasses must clear m_stylesheetReady
314      * themselves if needed.
315      *
316      * @param newProcessor ignored in this class
317      */
reset(boolean newProcessor)318     public void reset(boolean newProcessor)
319     {
320         m_params = null;
321         m_indent = NO_INDENT;
322     }
323 
324 
325     /**
326      * Static worker method to return default array of longs.
327      *
328      * Simply returns long[] pre-filled to TIME_UNUSED, suitable
329      * for returning from various transform API's.  May be called
330      * by external callers to get pre-sized array.
331      *
332      * @return long[] = TIME_UNUSED
333      */
getTimeArray()334     public static long[] getTimeArray()
335     {
336         return new long[]
337         {
338             TIME_UNUSED, /* IDX_OVERALL */
339             TIME_UNUSED, /* IDX_XSLREAD */
340             TIME_UNUSED, /* IDX_XSLBUILD */
341             TIME_UNUSED, /* IDX_XMLREAD */
342             TIME_UNUSED, /* IDX_XMLBUILD */
343             TIME_UNUSED, /* IDX_TRANSFORM */
344             TIME_UNUSED, /* IDX_RESULTWRITE */
345             TIME_UNUSED  /* IDX_FIRSTLATENCY */
346         };
347     }
348 
349 
350     /**
351      * Static worker method to return description of timing slots.
352      *
353      * @return String describing this idx slot in a getTimeArray
354      */
getTimeArrayDesc(int idx)355     public static String getTimeArrayDesc(int idx)
356     {
357         switch (idx)
358         {
359             case IDX_OVERALL:
360                 return "OVERALL";
361 
362             case IDX_XSLREAD:
363                 return "XSLREAD";
364 
365             case IDX_XSLBUILD:
366                 return "XSLBUILD";
367 
368             case IDX_XMLREAD:
369                 return "XMLREAD";
370 
371             case IDX_XMLBUILD:
372                 return "XMLBUILD";
373 
374             case IDX_TRANSFORM:
375                 return "TRANSFORM";
376 
377             case IDX_RESULTWRITE:
378                 return "RESULTWRITE";
379 
380             case IDX_FIRSTLATENCY:
381                 return "FIRSTLATENCY";
382 
383             default:
384                 return "ERROR:unknown-getTimeArrayDesc-idx";
385         }
386     }
387 }
388