KickJava   Java API By Example, From Geeks To Geeks.

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


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: ElemLiteralResult.java,v 1.42 2004/02/16 20:32:33 minchau Exp $
18  */

19 package org.apache.xalan.templates;
20
21 import java.util.Enumeration JavaDoc;
22 import java.util.Vector JavaDoc;
23
24 import javax.xml.transform.TransformerException JavaDoc;
25
26 import org.apache.xalan.transformer.TransformerImpl;
27 import org.apache.xml.serializer.SerializationHandler;
28 import org.apache.xml.utils.StringVector;
29 import org.apache.xpath.XPathContext;
30 import org.xml.sax.SAXException JavaDoc;
31
32 /**
33  * Implement a Literal Result Element.
34  * @see <a HREF="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
35  * @xsl.usage advanced
36  */

37 public class ElemLiteralResult extends ElemUse
38 {
39
40   /**
41    * Tells if this element represents a root element
42    * that is also the stylesheet element.
43    * TODO: This should be a derived class.
44    * @serial
45    */

46   private boolean isLiteralResultAsStylesheet = false;
47
48   /**
49    * Set whether this element represents a root element
50    * that is also the stylesheet element.
51    *
52    *
53    * @param b boolean flag indicating whether this element
54    * represents a root element that is also the stylesheet element.
55    */

56   public void setIsLiteralResultAsStylesheet(boolean b)
57   {
58     isLiteralResultAsStylesheet = b;
59   }
60
61   /**
62    * Return whether this element represents a root element
63    * that is also the stylesheet element.
64    *
65    *
66    * @return boolean flag indicating whether this element
67    * represents a root element that is also the stylesheet element.
68    */

69   public boolean getIsLiteralResultAsStylesheet()
70   {
71     return isLiteralResultAsStylesheet;
72   }
73   
74   /**
75    * This function is called after everything else has been
76    * recomposed, and allows the template to set remaining
77    * values that may be based on some other property that
78    * depends on recomposition.
79    */

80   public void compose(StylesheetRoot sroot) throws TransformerException JavaDoc
81   {
82     super.compose(sroot);
83     StylesheetRoot.ComposeState cstate = sroot.getComposeState();
84     java.util.Vector JavaDoc vnames = cstate.getVariableNames();
85     if (null != m_avts)
86     {
87       int nAttrs = m_avts.size();
88
89       for (int i = (nAttrs - 1); i >= 0; i--)
90       {
91         AVT avt = (AVT) m_avts.elementAt(i);
92         avt.fixupVariables(vnames, cstate.getGlobalsSize());
93       }
94     }
95   }
96   
97   /**
98    * The created element node will have the attribute nodes
99    * that were present on the element node in the stylesheet tree,
100    * other than attributes with names in the XSLT namespace.
101    * @serial
102    */

103   private Vector JavaDoc m_avts = null;
104
105   /** List of attributes with the XSLT namespace.
106    * @serial */

107   private Vector JavaDoc m_xslAttr = null;
108
109   /**
110    * Set a literal result attribute (AVTs only).
111    *
112    * @param avt literal result attribute to add (AVT only)
113    */

114   public void addLiteralResultAttribute(AVT avt)
115   {
116
117     if (null == m_avts)
118       m_avts = new Vector JavaDoc();
119
120     m_avts.addElement(avt);
121   }
122
123   /**
124    * Set a literal result attribute (used for xsl attributes).
125    *
126    * @param att literal result attribute to add
127    */

128   public void addLiteralResultAttribute(String JavaDoc att)
129   {
130
131     if (null == m_xslAttr)
132       m_xslAttr = new Vector JavaDoc();
133
134     m_xslAttr.addElement(att);
135   }
136   
137   /**
138    * Set the "xml:space" attribute.
139    * A text node is preserved if an ancestor element of the text node
140    * has an xml:space attribute with a value of preserve, and
141    * no closer ancestor element has xml:space with a value of default.
142    * @see <a HREF="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
143    * @see <a HREF="http://www.w3.org/TR/xslt#section-Creating-Text">section-Creating-Text in XSLT Specification</a>
144    *
145    * @param v Enumerated value, either Constants.ATTRVAL_PRESERVE
146    * or Constants.ATTRVAL_STRIP.
147    */

148   public void setXmlSpace(AVT avt)
149   {
150     // This function is a bit-o-hack, I guess...
151
addLiteralResultAttribute(avt);
152     String JavaDoc val = avt.getSimpleString();
153     if(val.equals("default"))
154     {
155       super.setXmlSpace(Constants.ATTRVAL_STRIP);
156     }
157     else if(val.equals("preserve"))
158     {
159       super.setXmlSpace(Constants.ATTRVAL_PRESERVE);
160     }
161     // else maybe it's a real AVT, so we can't resolve it at this time.
162
}
163
164
165   /**
166    * Get a literal result attribute by name.
167    *
168    * @param name Name of literal result attribute to get
169    *
170    * @return literal result attribute (AVT)
171    */

172   public AVT getLiteralResultAttribute(String JavaDoc name)
173   {
174
175     if (null != m_avts)
176     {
177       int nAttrs = m_avts.size();
178
179       for (int i = (nAttrs - 1); i >= 0; i--)
180       {
181         AVT avt = (AVT) m_avts.elementAt(i);
182
183         if (avt.getRawName().equals(name))
184         {
185           return avt;
186         }
187       } // end for
188
}
189
190     return null;
191   }
192
193   /**
194    * Get whether or not the passed URL is flagged by
195    * the "extension-element-prefixes" or "exclude-result-prefixes"
196    * properties.
197    * @see <a HREF="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
198    *
199    * @param prefix non-null reference to prefix that might be excluded.(not currently used)
200    * @param uri reference to namespace that prefix maps to
201    *
202    * @return true if the prefix should normally be excluded.
203    */

204   public boolean containsExcludeResultPrefix(String JavaDoc prefix, String JavaDoc uri)
205   {
206     if (uri == null ||
207                 (null == m_excludeResultPrefixes &&
208                  null == m_ExtensionElementURIs)
209                 )
210       return super.containsExcludeResultPrefix(prefix, uri);
211
212     if (prefix.length() == 0)
213       prefix = Constants.ATTRVAL_DEFAULT_PREFIX;
214
215     // This loop is ok here because this code only runs during
216
// stylesheet compile time.
217
if(m_excludeResultPrefixes!=null)
218             for (int i =0; i< m_excludeResultPrefixes.size(); i++)
219             {
220                 if (uri.equals(getNamespaceForPrefix(m_excludeResultPrefixes.elementAt(i))))
221                     return true;
222             }
223         
224         // JJK Bugzilla 1133: Also check locally-scoped extensions
225
if(m_ExtensionElementURIs!=null && m_ExtensionElementURIs.contains(uri))
226        return true;
227
228         return super.containsExcludeResultPrefix(prefix, uri);
229   }
230
231   /**
232    * Augment resolvePrefixTables, resolving the namespace aliases once
233    * the superclass has resolved the tables.
234    *
235    * @throws TransformerException
236    */

237   public void resolvePrefixTables() throws TransformerException JavaDoc
238   {
239
240     super.resolvePrefixTables();
241
242     StylesheetRoot stylesheet = getStylesheetRoot();
243
244     if ((null != m_namespace) && (m_namespace.length() > 0))
245     {
246       NamespaceAlias nsa = stylesheet.getNamespaceAliasComposed(m_namespace);
247
248       if (null != nsa)
249       {
250         m_namespace = nsa.getResultNamespace();
251
252         // String resultPrefix = nsa.getResultPrefix();
253
String JavaDoc resultPrefix = nsa.getStylesheetPrefix(); // As per xsl WG, Mike Kay
254

255         if ((null != resultPrefix) && (resultPrefix.length() > 0))
256           m_rawName = resultPrefix + ":" + m_localName;
257         else
258           m_rawName = m_localName;
259       }
260     }
261
262     if (null != m_avts)
263     {
264       int n = m_avts.size();
265
266       for (int i = 0; i < n; i++)
267       {
268         AVT avt = (AVT) m_avts.elementAt(i);
269
270         // Should this stuff be a method on AVT?
271
String JavaDoc ns = avt.getURI();
272
273         if ((null != ns) && (ns.length() > 0))
274         {
275           NamespaceAlias nsa =
276             stylesheet.getNamespaceAliasComposed(m_namespace); // %REVIEW% ns?
277

278           if (null != nsa)
279           {
280             String JavaDoc namespace = nsa.getResultNamespace();
281
282             // String resultPrefix = nsa.getResultPrefix();
283
String JavaDoc resultPrefix = nsa.getStylesheetPrefix(); // As per XSL WG
284
String JavaDoc rawName = avt.getName();
285
286             if ((null != resultPrefix) && (resultPrefix.length() > 0))
287               rawName = resultPrefix + ":" + rawName;
288
289             avt.setURI(namespace);
290             avt.setRawName(rawName);
291           }
292         }
293       }
294     }
295   }
296
297   /**
298    * Return whether we need to check namespace prefixes
299    * against the exclude result prefixes or extensions lists.
300    * Note that this will create a new prefix table if one
301    * has not been created already.
302    *
303    * NEEDSDOC ($objectName$) @return
304    */

305   boolean needToCheckExclude()
306   {
307     if (null == m_excludeResultPrefixes && null == m_prefixTable
308                 && m_ExtensionElementURIs==null // JJK Bugzilla 1133
309
)
310       return false;
311     else
312     {
313
314       // Create a new prefix table if one has not already been created.
315
if (null == m_prefixTable)
316         m_prefixTable = new Vector JavaDoc();
317
318       return true;
319     }
320   }
321
322   /**
323    * The namespace of the element to be created.
324    * @serial
325    */

326   private String JavaDoc m_namespace;
327
328   /**
329    * Set the namespace URI of the result element to be created.
330    * Note that after resolvePrefixTables has been called, this will
331    * return the aliased result namespace, not the original stylesheet
332    * namespace.
333    *
334    * @param ns The Namespace URI, or the empty string if the
335    * element has no Namespace URI.
336    */

337   public void setNamespace(String JavaDoc ns)
338   {
339     if(null == ns) // defensive, shouldn't have to do this.
340
ns = "";
341     m_namespace = ns;
342   }
343
344   /**
345    * Get the original namespace of the Literal Result Element.
346    *
347    * %REVIEW% Why isn't this overriding the getNamespaceURI method
348    * rather than introducing a new one?
349    *
350    * @return The Namespace URI, or the empty string if the
351    * element has no Namespace URI.
352    */

353   public String JavaDoc getNamespace()
354   {
355     return m_namespace;
356   }
357
358   /**
359    * The local name of the element to be created.
360    * @serial
361    */

362   private String JavaDoc m_localName;
363
364   /**
365    * Set the local name of the LRE.
366    *
367    * @param localName The local name (without prefix) of the result element
368    * to be created.
369    */

370   public void setLocalName(String JavaDoc localName)
371   {
372     m_localName = localName;
373   }
374
375   /**
376    * Get the local name of the Literal Result Element.
377    * Note that after resolvePrefixTables has been called, this will
378    * return the aliased name prefix, not the original stylesheet
379    * namespace prefix.
380    *
381    * @return The local name (without prefix) of the result element
382    * to be created.
383    */

384   public String JavaDoc getLocalName()
385   {
386     return m_localName;
387   }
388
389   /**
390    * The raw name of the element to be created.
391    * @serial
392    */

393   private String JavaDoc m_rawName;
394
395   /**
396    * Set the raw name of the LRE.
397    *
398    * @param rawName The qualified name (with prefix), or the
399    * empty string if qualified names are not available.
400    */

401   public void setRawName(String JavaDoc rawName)
402   {
403     m_rawName = rawName;
404   }
405
406   /**
407    * Get the raw name of the Literal Result Element.
408    *
409    * @return The qualified name (with prefix), or the
410    * empty string if qualified names are not available.
411    */

412   public String JavaDoc getRawName()
413   {
414     return m_rawName;
415   }
416     
417  /**
418    * Get the prefix part of the raw name of the Literal Result Element.
419    *
420    * @return The prefix, or the empty string if noprefix was provided.
421    */

422   public String JavaDoc getPrefix()
423   {
424         int len=m_rawName.length()-m_localName.length()-1;
425     return (len>0)
426             ? m_rawName.substring(0,len)
427             : "";
428   }
429
430
431   /**
432    * The "extension-element-prefixes" property, actually contains URIs.
433    * @serial
434    */

435   private StringVector m_ExtensionElementURIs;
436
437   /**
438    * Set the "extension-element-prefixes" property.
439    * @see <a HREF="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
440    *
441    * @param v Vector of URIs (not prefixes) to set as the "extension-element-prefixes" property
442    */

443   public void setExtensionElementPrefixes(StringVector v)
444   {
445     m_ExtensionElementURIs = v;
446   }
447
448   /**
449    * Get an "extension-element-prefix" property.
450    * @see <a HREF="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
451    *
452    * @param i Index of URI ("extension-element-prefix" property) to get
453    *
454    * @return URI at given index ("extension-element-prefix" property)
455    *
456    * @throws ArrayIndexOutOfBoundsException
457    */

458   public String JavaDoc getExtensionElementPrefix(int i)
459           throws ArrayIndexOutOfBoundsException JavaDoc
460   {
461
462     if (null == m_ExtensionElementURIs)
463       throw new ArrayIndexOutOfBoundsException JavaDoc();
464
465     return m_ExtensionElementURIs.elementAt(i);
466   }
467
468   /**
469    * Get the number of "extension-element-prefixes" Strings.
470    * @see <a HREF="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
471    *
472    * @return the number of "extension-element-prefixes" Strings
473    */

474   public int getExtensionElementPrefixCount()
475   {
476     return (null != m_ExtensionElementURIs)
477            ? m_ExtensionElementURIs.size() : 0;
478   }
479
480   /**
481    * Find out if the given "extension-element-prefix" property is defined.
482    * @see <a HREF="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
483    *
484    * @param uri The URI to find
485    *
486    * @return True if the given URI is found
487    */

488   public boolean containsExtensionElementURI(String JavaDoc uri)
489   {
490
491     if (null == m_ExtensionElementURIs)
492       return false;
493
494     return m_ExtensionElementURIs.contains(uri);
495   }
496
497   /**
498    * Get an int constant identifying the type of element.
499    * @see org.apache.xalan.templates.Constants
500    *
501    * @return The token ID for this element
502    */

503   public int getXSLToken()
504   {
505     return Constants.ELEMNAME_LITERALRESULT;
506   }
507
508   /**
509    * Return the node name.
510    *
511    * @return The element's name
512    */

513   public String JavaDoc getNodeName()
514   {
515
516     // TODO: Need prefix.
517
return m_rawName;
518   }
519
520   /**
521    * The XSLT version as specified by this element.
522    * @serial
523    */

524   private String JavaDoc m_version;
525
526   /**
527    * Set the "version" property.
528    * @see <a HREF="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
529    *
530    * @param v Version property value to set
531    */

532   public void setVersion(String JavaDoc v)
533   {
534     m_version = v;
535   }
536   
537   /**
538    * Get the "version" property.
539    * @see <a HREF="http://www.w3.org/TR/xslt#forwards">forwards in XSLT Specification</a>
540    *
541    * @return Version property value
542    */

543   public String JavaDoc getVersion()
544   {
545     return m_version;
546   }
547
548   /**
549    * The "exclude-result-prefixes" property.
550    * @serial
551    */

552   private StringVector m_excludeResultPrefixes;
553
554   /**
555    * Set the "exclude-result-prefixes" property.
556    * The designation of a namespace as an excluded namespace is
557    * effective within the subtree of the stylesheet rooted at
558    * the element bearing the exclude-result-prefixes or
559    * xsl:exclude-result-prefixes attribute; a subtree rooted
560    * at an xsl:stylesheet element does not include any stylesheets
561    * imported or included by children of that xsl:stylesheet element.
562    * @see <a HREF="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
563    *
564    * @param v vector of prefixes that are resolvable to strings.
565    */

566   public void setExcludeResultPrefixes(StringVector v)
567   {
568     m_excludeResultPrefixes = v;
569   }
570
571   /**
572    * Tell if the result namespace decl should be excluded. Should be called before
573    * namespace aliasing (I think).
574    *
575    * @param prefix Prefix of namespace to check
576    * @param uri URI of namespace to check
577    *
578    * @return True if the given namespace should be excluded
579    *
580    * @throws TransformerException
581    */

582   private boolean excludeResultNSDecl(String JavaDoc prefix, String JavaDoc uri)
583           throws TransformerException JavaDoc
584   {
585
586     if (null != m_excludeResultPrefixes)
587     {
588       return containsExcludeResultPrefix(prefix, uri);
589     }
590
591     return false;
592   }
593   
594   /**
595    * Copy a Literal Result Element into the Result tree, copy the
596    * non-excluded namespace attributes, copy the attributes not
597    * of the XSLT namespace, and execute the children of the LRE.
598    * @see <a HREF="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
599    *
600    * @param transformer non-null reference to the the current transform-time state.
601    * @param sourceNode non-null reference to the <a HREF="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
602    * @param mode reference, which may be null, to the <a HREF="http://www.w3.org/TR/xslt#modes">current mode</a>.
603    *
604    * @throws TransformerException
605    */

606     public void execute(TransformerImpl transformer)
607         throws TransformerException JavaDoc
608     {
609         SerializationHandler rhandler = transformer.getSerializationHandler();
610
611         try
612         {
613             if (TransformerImpl.S_DEBUG) {
614                 // flush any buffered pending processing before
615
// the trace event.
616
rhandler.flushPending();
617                 transformer.getTraceManager().fireTraceEvent(this);
618             }
619
620             // JJK Bugzilla 3464, test namespace85 -- make sure LRE's
621
// namespace is asserted even if default, since xsl:element
622
// may have changed the context.
623
rhandler.startPrefixMapping(getPrefix(), getNamespace());
624
625             // Add namespace declarations.
626
executeNSDecls(transformer);
627             rhandler.startElement(getNamespace(), getLocalName(), getRawName());
628         }
629         catch (SAXException JavaDoc se)
630         {
631             throw new TransformerException JavaDoc(se);
632         }
633
634         /*
635          * If we make it to here we have done a successful startElement()
636          * we will do an endElement() call for balance, no matter what happens
637          * in the middle.
638          */

639
640         // tException remembers if we had an exception "in the middle"
641
TransformerException JavaDoc tException = null;
642         try
643         {
644
645             // Process any possible attributes from xsl:use-attribute-sets first
646
super.execute(transformer);
647
648             //xsl:version, excludeResultPrefixes???
649
// Process the list of avts next
650
if (null != m_avts)
651             {
652                 int nAttrs = m_avts.size();
653
654                 for (int i = (nAttrs - 1); i >= 0; i--)
655                 {
656                     AVT avt = (AVT) m_avts.elementAt(i);
657                     XPathContext xctxt = transformer.getXPathContext();
658                     int sourceNode = xctxt.getCurrentNode();
659                     String JavaDoc stringedValue =
660                         avt.evaluate(xctxt, sourceNode, this);
661
662                     if (null != stringedValue)
663                     {
664
665                         // Important Note: I'm not going to check for excluded namespace
666
// prefixes here. It seems like it's too expensive, and I'm not
667
// even sure this is right. But I could be wrong, so this needs
668
// to be tested against other implementations.
669

670                         rhandler.addAttribute(
671                             avt.getURI(),
672                             avt.getName(),
673                             avt.getRawName(),
674                             "CDATA",
675                             stringedValue);
676                     }
677                 } // end for
678
}
679
680             // Now process all the elements in this subtree
681
// TODO: Process m_extensionElementPrefixes && m_attributeSetsNames
682
transformer.executeChildTemplates(this, true);
683         }
684         catch (TransformerException JavaDoc te)
685         {
686             // thrown in finally to prevent original exception consumed by subsequent exceptions
687
tException = te;
688         }
689         catch (SAXException JavaDoc se)
690         {
691             tException = new TransformerException JavaDoc(se);
692         }
693
694         try
695         {
696             /* we need to do this endElement() to balance the
697              * successful startElement() call even if
698              * there was an exception in the middle.
699              * Otherwise an exception in the middle could cause a system to hang.
700              */

701             if (TransformerImpl.S_DEBUG) {
702                 // flush any buffered pending processing before
703
// the trace event.
704
//rhandler.flushPending();
705
transformer.getTraceManager().fireTraceEndEvent(this);
706             }
707             rhandler.endElement(getNamespace(), getLocalName(), getRawName());
708         }
709         catch (SAXException JavaDoc se)
710         {
711             /* we did call endElement(). If thee was an exception
712              * in the middle throw that one, otherwise if there
713              * was an exception from endElement() throw that one.
714              */

715             if (tException != null)
716                 throw tException;
717             else
718                 throw new TransformerException JavaDoc(se);
719         }
720         
721         /* If an exception was thrown in the middle but not with startElement() or
722          * or endElement() then its time to let it percolate.
723          */

724         if (tException != null)
725             throw tException;
726         
727         unexecuteNSDecls(transformer);
728
729         // JJK Bugzilla 3464, test namespace85 -- balance explicit start.
730
try
731         {
732             rhandler.endPrefixMapping(getPrefix());
733         }
734         catch (SAXException JavaDoc se)
735         {
736             throw new TransformerException JavaDoc(se);
737         }
738     }
739
740   /**
741    * Compiling templates requires that we be able to list the AVTs
742    * ADDED 9/5/2000 to support compilation experiment
743    *
744    * @return an Enumeration of the literal result attributes associated
745    * with this element.
746    */

747   public Enumeration JavaDoc enumerateLiteralResultAttributes()
748   {
749     return (null == m_avts) ? null : m_avts.elements();
750   }
751   
752     /**
753      * Accept a visitor and call the appropriate method
754      * for this class.
755      *
756      * @param visitor The visitor whose appropriate method will be called.
757      * @return true if the children of the object should be visited.
758      */

759     protected boolean accept(XSLTVisitor visitor)
760     {
761       return visitor.visitLiteralResultElement(this);
762     }
763
764     /**
765      * Call the children visitors.
766      * @param visitor The visitor whose appropriate method will be called.
767      */

768     protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
769     {
770       if (callAttrs && null != m_avts)
771       {
772         int nAttrs = m_avts.size();
773
774         for (int i = (nAttrs - 1); i >= 0; i--)
775         {
776           AVT avt = (AVT) m_avts.elementAt(i);
777           avt.callVisitors(visitor);
778         }
779       }
780       super.callChildVisitors(visitor, callAttrs);
781     }
782
783 }
784
Popular Tags