KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > templates > AVT


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: AVT.java,v 1.22 2004/02/16 20:32:32 minchau Exp $
18  */

19 package org.apache.xalan.templates;
20
21 import java.util.StringTokenizer JavaDoc;
22 import java.util.Vector JavaDoc;
23
24 import javax.xml.transform.TransformerException JavaDoc;
25
26 import org.apache.xalan.processor.StylesheetHandler;
27 import org.apache.xalan.res.XSLMessages;
28 import org.apache.xalan.res.XSLTErrorResources;
29 import org.apache.xml.utils.FastStringBuffer;
30 import org.apache.xml.utils.StringBufferPool;
31 import org.apache.xpath.XPath;
32 import org.apache.xpath.XPathContext;
33
34 /**
35  * Class to hold an Attribute Value Template.
36  * @xsl.usage advanced
37  */

38 public class AVT implements java.io.Serializable JavaDoc, XSLTVisitable
39 {
40
41   /**
42    * If the AVT is not complex, just hold the simple string.
43    * @serial
44    */

45   private String JavaDoc m_simpleString = null;
46
47   /**
48    * If the AVT is complex, hold a Vector of AVTParts.
49    * @serial
50    */

51   private Vector JavaDoc m_parts = null;
52
53   /**
54    * The name of the attribute.
55    * @serial
56    */

57   private String JavaDoc m_rawName;
58
59   /**
60    * Get the raw name of the attribute, with the prefix unprocessed.
61    *
62    * @return non-null reference to prefixed name.
63    */

64   public String JavaDoc getRawName()
65   {
66     return m_rawName;
67   }
68
69   /**
70    * Get the raw name of the attribute, with the prefix unprocessed.
71    *
72    * @param rawName non-null reference to prefixed name.
73    */

74   public void setRawName(String JavaDoc rawName)
75   {
76     m_rawName = rawName;
77   }
78
79   /**
80    * The name of the attribute.
81    * @serial
82    */

83   private String JavaDoc m_name;
84
85   /**
86    * Get the local name of the attribute.
87    *
88    * @return non-null reference to name string.
89    */

90   public String JavaDoc getName()
91   {
92     return m_name;
93   }
94
95   /**
96    * Set the local name of the attribute.
97    *
98    * @param name non-null reference to name string.
99    */

100   public void setName(String JavaDoc name)
101   {
102     m_name = name;
103   }
104
105   /**
106    * The namespace URI of the owning attribute.
107    * @serial
108    */

109   private String JavaDoc m_uri;
110
111   /**
112    * Get the namespace URI of the attribute.
113    *
114    * @return non-null reference to URI, "" if null namespace.
115    */

116   public String JavaDoc getURI()
117   {
118     return m_uri;
119   }
120
121   /**
122    * Get the namespace URI of the attribute.
123    *
124    * @param uri non-null reference to URI, "" if null namespace.
125    */

126   public void setURI(String JavaDoc uri)
127   {
128     m_uri = uri;
129   }
130
131   /**
132    * Construct an AVT by parsing the string, and either
133    * constructing a vector of AVTParts, or simply hold
134    * on to the string if the AVT is simple.
135    *
136    * @param handler non-null reference to StylesheetHandler that is constructing.
137    * @param uri non-null reference to URI, "" if null namespace.
138    * @param name non-null reference to name string.
139    * @param rawName prefixed name.
140    * @param stringedValue non-null raw string value.
141    *
142    * @throws javax.xml.transform.TransformerException
143    */

144   public AVT(StylesheetHandler handler, String JavaDoc uri, String JavaDoc name,
145              String JavaDoc rawName, String JavaDoc stringedValue,
146              ElemTemplateElement owner)
147           throws javax.xml.transform.TransformerException JavaDoc
148   {
149
150     m_uri = uri;
151     m_name = name;
152     m_rawName = rawName;
153
154     StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(stringedValue, "{}\"\'",
155                                   true);
156     int nTokens = tokenizer.countTokens();
157
158     if (nTokens < 2)
159     {
160       m_simpleString = stringedValue; // then do the simple thing
161
}
162     else
163     {
164       FastStringBuffer buffer = StringBufferPool.get();
165       FastStringBuffer exprBuffer = StringBufferPool.get();
166
167       try
168       {
169         m_parts = new Vector JavaDoc(nTokens + 1);
170
171         String JavaDoc t = null; // base token
172
String JavaDoc lookahead = null; // next token
173
String JavaDoc error = null; // if non-null, break from loop
174

175         while (tokenizer.hasMoreTokens())
176         {
177           if (lookahead != null)
178           {
179             t = lookahead;
180             lookahead = null;
181           }
182           else
183             t = tokenizer.nextToken();
184
185           if (t.length() == 1)
186           {
187             switch (t.charAt(0))
188             {
189             case ('\"') :
190             case ('\'') :
191             {
192
193               // just keep on going, since we're not in an attribute template
194
buffer.append(t);
195
196               break;
197             }
198             case ('{') :
199             {
200
201               try
202               {
203                 // Attribute Value Template start
204
lookahead = tokenizer.nextToken();
205
206                 if (lookahead.equals("{"))
207                 {
208
209                   // Double curlys mean escape to show curly
210
buffer.append(lookahead);
211
212                   lookahead = null;
213
214                   break; // from switch
215
}
216
217                 /*
218                 else if(lookahead.equals("\"") || lookahead.equals("\'"))
219                 {
220                 // Error. Expressions can not begin with quotes.
221                 error = "Expressions can not begin with quotes.";
222                 break; // from switch
223                 }
224                 */

225                 else
226                 {
227                   if (buffer.length() > 0)
228                   {
229                     m_parts.addElement(new AVTPartSimple(buffer.toString()));
230                     buffer.setLength(0);
231                   }
232
233                   exprBuffer.setLength(0);
234
235                   while (null != lookahead)
236                   {
237                     if (lookahead.length() == 1)
238                     {
239                       switch (lookahead.charAt(0))
240                       {
241                       case '\'' :
242                       case '\"' :
243                         {
244
245                           // String start
246
exprBuffer.append(lookahead);
247
248                           String JavaDoc quote = lookahead;
249
250                           // Consume stuff 'till next quote
251
lookahead = tokenizer.nextToken();
252
253                           while (!lookahead.equals(quote))
254                           {
255                             exprBuffer.append(lookahead);
256
257                             lookahead = tokenizer.nextToken();
258                           }
259
260                           exprBuffer.append(lookahead);
261
262                           lookahead = tokenizer.nextToken();
263
264                           break;
265                         }
266                       case '{' :
267                         {
268
269                           // What's another curly doing here?
270
error = XSLMessages.createMessage(
271                                                             XSLTErrorResources.ER_NO_CURLYBRACE, null); //"Error: Can not have \"{\" within expression.";
272

273                           lookahead = null; // breaks out of inner while loop
274

275                           break;
276                         }
277                       case '}' :
278                         {
279
280                           // Proper close of attribute template.
281
// Evaluate the expression.
282
buffer.setLength(0);
283
284                           XPath xpath =
285                                        handler.createXPath(exprBuffer.toString(), owner);
286
287                           m_parts.addElement(new AVTPartXPath(xpath));
288
289                           lookahead = null; // breaks out of inner while loop
290

291                           break;
292                         }
293                       default :
294                         {
295
296                           // part of the template stuff, just add it.
297
exprBuffer.append(lookahead);
298
299                           lookahead = tokenizer.nextToken();
300                         }
301                       } // end inner switch
302
} // end if lookahead length == 1
303
else
304                     {
305
306                       // part of the template stuff, just add it.
307
exprBuffer.append(lookahead);
308
309                       lookahead = tokenizer.nextToken();
310                     }
311                   } // end while(!lookahead.equals("}"))
312

313                   if (error != null)
314                   {
315                     break; // from inner while loop
316
}
317                 }
318
319                 break;
320               }
321               catch (java.util.NoSuchElementException JavaDoc ex)
322               {
323                 error = XSLMessages.createMessage(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE, new Object JavaDoc[]{ name, stringedValue });
324                 break;
325               }
326             }
327             case ('}') :
328             {
329               lookahead = tokenizer.nextToken();
330
331               if (lookahead.equals("}"))
332               {
333
334                 // Double curlys mean escape to show curly
335
buffer.append(lookahead);
336
337                 lookahead = null; // swallow
338
}
339               else
340               {
341
342                 // Illegal, I think...
343
try
344                 {
345                   handler.warn(XSLTErrorResources.WG_FOUND_CURLYBRACE, null); //"Found \"}\" but no attribute template open!");
346
}
347                 catch (org.xml.sax.SAXException JavaDoc se)
348                 {
349                   throw new TransformerException JavaDoc(se);
350                 }
351
352                 buffer.append("}");
353
354                 // leave the lookahead to be processed by the next round.
355
}
356
357               break;
358             }
359             default :
360             {
361
362               // Anything else just add to string.
363
buffer.append(t);
364             }
365             } // end switch t
366
} // end if length == 1
367
else
368           {
369
370             // Anything else just add to string.
371
buffer.append(t);
372           }
373
374           if (null != error)
375           {
376             try
377             {
378               handler.warn(XSLTErrorResources.WG_ATTR_TEMPLATE,
379                            new Object JavaDoc[]{ error }); //"Attr Template, "+error);
380
}
381             catch (org.xml.sax.SAXException JavaDoc se)
382             {
383               throw new TransformerException JavaDoc(se);
384             }
385
386             break;
387           }
388         } // end while(tokenizer.hasMoreTokens())
389

390         if (buffer.length() > 0)
391         {
392           m_parts.addElement(new AVTPartSimple(buffer.toString()));
393           buffer.setLength(0);
394         }
395       }
396       finally
397       {
398         StringBufferPool.free(buffer);
399         StringBufferPool.free(exprBuffer);
400       }
401     } // end else nTokens > 1
402

403     if (null == m_parts && (null == m_simpleString))
404     {
405
406       // Error?
407
m_simpleString = "";
408     }
409   }
410
411   /**
412    * Get the AVT as the original string.
413    *
414    * @return The AVT as the original string
415    */

416   public String JavaDoc getSimpleString()
417   {
418
419     if (null != m_simpleString)
420     {
421       return m_simpleString;
422     }
423     else if (null != m_parts)
424     {
425       FastStringBuffer buf = StringBufferPool.get();
426       String JavaDoc s;
427
428       try
429       {
430         buf.setLength(0);
431
432         int n = m_parts.size();
433
434         for (int i = 0; i < n; i++)
435         {
436           AVTPart part = (AVTPart) m_parts.elementAt(i);
437
438           buf.append(part.getSimpleString());
439         }
440
441         s = buf.toString();
442       }
443       finally
444       {
445         StringBufferPool.free(buf);
446       }
447
448       return s;
449     }
450     else
451     {
452       return "";
453     }
454   }
455
456   /**
457    * Evaluate the AVT and return a String.
458    *
459    * @param xctxt Te XPathContext to use to evaluate this.
460    * @param context The current source tree context.
461    * @param nsNode The current namespace context (stylesheet tree context).
462    * @param NodeList The current Context Node List.
463    *
464    * @return The AVT evaluated as a string
465    *
466    * @throws javax.xml.transform.TransformerException
467    */

468   public String JavaDoc evaluate(
469           XPathContext xctxt, int context, org.apache.xml.utils.PrefixResolver nsNode)
470             throws javax.xml.transform.TransformerException JavaDoc
471   {
472
473     FastStringBuffer buf = StringBufferPool.get();
474
475     try
476     {
477       if (null != m_simpleString)
478       {
479         return m_simpleString;
480       }
481       else if (null != m_parts)
482       {
483         buf.setLength(0);
484
485         int n = m_parts.size();
486
487         for (int i = 0; i < n; i++)
488         {
489           AVTPart part = (AVTPart) m_parts.elementAt(i);
490
491           part.evaluate(xctxt, buf, context, nsNode);
492         }
493
494         return buf.toString();
495       }
496       else
497       {
498         return "";
499       }
500     }
501     finally
502     {
503       StringBufferPool.free(buf);
504     }
505   }
506
507   /**
508    * Test whether the AVT is insensitive to the context in which
509    * it is being evaluated. This is intended to facilitate
510    * compilation of templates, by allowing simple AVTs to be
511    * converted back into strings.
512    *
513    * Currently the only case we recognize is simple strings.
514    * ADDED 9/5/2000 to support compilation experiment
515    *
516    * @return True if the m_simpleString member of this AVT is not null
517    */

518   public boolean isContextInsensitive()
519   {
520     return null != m_simpleString;
521   }
522
523   /**
524    * Tell if this expression or it's subexpressions can traverse outside
525    * the current subtree.
526    *
527    * @return true if traversal outside the context node's subtree can occur.
528    */

529   public boolean canTraverseOutsideSubtree()
530   {
531
532     if (null != m_parts)
533     {
534       int n = m_parts.size();
535
536       for (int i = 0; i < n; i++)
537       {
538         AVTPart part = (AVTPart) m_parts.elementAt(i);
539
540         if (part.canTraverseOutsideSubtree())
541           return true;
542       }
543     }
544
545     return false;
546   }
547   
548   /**
549    * This function is used to fixup variables from QNames to stack frame
550    * indexes at stylesheet build time.
551    * @param vars List of QNames that correspond to variables. This list
552    * should be searched backwards for the first qualified name that
553    * corresponds to the variable reference qname. The position of the
554    * QName in the vector from the start of the vector will be its position
555    * in the stack frame (but variables above the globalsTop value will need
556    * to be offset to the current stack frame).
557    */

558   public void fixupVariables(java.util.Vector JavaDoc vars, int globalsSize)
559   {
560     if (null != m_parts)
561     {
562       int n = m_parts.size();
563
564       for (int i = 0; i < n; i++)
565       {
566         AVTPart part = (AVTPart) m_parts.elementAt(i);
567
568         part.fixupVariables(vars, globalsSize);
569       }
570     }
571   }
572   
573   /**
574    * @see XSLTVisitable#callVisitors(XSLTVisitor)
575    */

576   public void callVisitors(XSLTVisitor visitor)
577   {
578     if(visitor.visitAVT(this) && (null != m_parts))
579     {
580       int n = m_parts.size();
581
582       for (int i = 0; i < n; i++)
583       {
584         AVTPart part = (AVTPart) m_parts.elementAt(i);
585
586         part.callVisitors(visitor);
587       }
588     }
589   }
590
591
592   /**
593    * Returns true if this AVT is simple
594    */

595   public boolean isSimple() {
596     return m_simpleString != null;
597   }
598 }
599
Popular Tags